功夫Panda

记录一些遇到的问题

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  47 随笔 :: 0 文章 :: 18 评论 :: 68万 阅读
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

今天在友元类与命名空间结合使用时,遇到一个小问题,总结一下。

这样一个场景:

A是一个连接类,B是一个客户端类,在不同的命名空间下,在不同的头文件定义,

A希望B能够访问到自己的私有成员,所以设置B为其友元类,

B类在实例化时,需要用到A类对象进行初始化(构造函数用到A类对象指针)。

 

涉及到了头文件相互包含的问题,头文件中对所需的类类型进行前向声明(forward declaration),然后在.cpp文件中包含该类类型的头文件,

详细说明可参考http://www.cnblogs.com/sunrack/articles/590384.html

 

对不同命名空间的类型进行前向声明时,以下列方式声明,使用该类型时,需指定其所在命名空间

namespace space_name {
class type_name;
}

 

这里遇到了一个问题,

如果一个类(类型名是A)在特定命名空间(名字是nsa)下,而其友元类(类型名是B)在全局空间下,进行友元类声明时,目标类使用全局空间域操作符,

否则,A类会认为B类在nsa下,实际上B类在global空间下,所以导致编译的时候,提示B类没有权限使用A类的私有的数据或函数成员。

Linux下这个规则需要严格遵守,在Windows下使用dev-c++发现即使B类不指定全局空间,也能正常编译和运行,可能是编译器实现上不同吧。。

总结一下,涉及到不同命名空间的友元类声明,一定要指定其所在命名空间。

 

demo代码如下

a.h

复制代码
#ifndef A_H
#define A_H

//forward declaration
namespace nsb {
class B;
}

namespace nsa {

class A {
public:
    A(): num_(0) {}
    int get_num() const { return num_; }

    friend class nsb::B;
    //friend class ::B; //if B is in global namespace, need to use "::B"

private:
    int num_;
};

} // namespace

#endif
复制代码

b.h

复制代码
#ifndef B_H
#define B_H

//forward declaration
namespace nsa {
class A;
}

namespace nsb {

class B {
public:
    B(nsa::A *a);
    void set_num_of_A(int n);
    int get_num_of_A() const;

private:
    nsa::A *pa_;
};

} // namespace

#endif
复制代码

b.cpp

复制代码
#include "b.h"
#include "a.h"

namespace nsb {

B::B(nsa::A *pa): pa_(pa) {
}

void B::set_num_of_A(int n) {
    pa_->num_ = n;
}

int B::get_num_of_A() const {
    return pa_->num_;
}

} // namespace
复制代码

test.cpp

复制代码
#include "a.h"
#include "b.h"

#include <iostream>
using std::cout;
using std::endl;

int main() {
    nsa::A a;
    nsb::B b(&a);
    cout << a.get_num() << endl;
    b.set_num_of_A(100);
    cout << b.get_num_of_A() << endl;
    return 0;
}
复制代码

 

 

 

 

 

 

posted on   功夫Panda  阅读(3612)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?

点击右上角即可分享
微信分享提示