zoukankan      html  css  js  c++  java
  • C++友元类与命名空间的结合使用

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

    这样一个场景:

    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;
    }
    From http://www.cnblogs.com/caosiyang/
  • 相关阅读:
    归并排序处理复杂对象例子
    Java归并排序的递归与非递归实现
    Java实现一个双向链表的倒置功能
    Node<T> 的作用
    Tomcat控制台总是打印日志问题的解决办法
    git回滚部分文件到某个版本
    ios-deploy was not found
    Ionic3的http请求如何实现token验证,并且超时返回登录页
    Ionic开发遇到的坑整理
    使用gradle命令代替CUBA Studio,启动项目
  • 原文地址:https://www.cnblogs.com/caosiyang/p/2731274.html
Copyright © 2011-2022 走看看