全局命名空间朋友 class 无法访问命名空间 class 的私有成员

Global namespace friend class cannot access private member of named namespace class

在命名空间 class 中,我将 class(在全局空间中)声明为友元。 但是,后者class无法访问前者class的私有成员。为什么是这样?有什么解决办法吗?

Bob.h

namespace ABC {
    class Bob {
        friend class Joe;
        public:
            Bob ();
            int pub_number;
        private:
            int priv_number;
    };
}

Bob.cc

#include "Bob.h"

ABC::Bob::Bob () {
    pub_number=10;
    priv_number=6;
}

Joe.h

class Joe {
    Joe ( );
};

Joe.cc

#include "Joe.h"
#include <iostream>
#include "Bob.h"

Joe::Joe ( ) {
    ABC::Bob b;
    std::cout << b.pub_number << std::endl;
    std::cout << b.priv_number << std::endl;
}

以上代码在编译时产生如下错误:

Joe.cc:8:16: error: ‘int ABC::Bob::priv_number’ is private within this context
INFO: 1>     8 | std::cout << b.priv_number << std::endl;

如果我执行与上面相同的代码,但没有为“Bob”class 命名空间,则代码可以编译。

我已尝试在 Bob.h 中转发声明乔 class 如下:

class Joe; // This does nothing to help

class ::Joe // This produces compiler message "error: ‘Joe’ in namespace ‘::’ does not name a type"

您的 friend 声明也需要 :: 前缀:

class Joe;

namespace ABC {
    class Bob {
        friend class ::Joe;
        //           ^^ here

        ...
     };
 }

您需要在全局命名空间中添加无作用域的前向声明,并在声明友元时使用作用域运算符:

class Joe;  // Forward declaration

namespace ABC {
    class Bob {
        friend class ::Joe;  // Use the Joe class from the global scope
        public:
            Bob ();
            int pub_number;
        private:
            int priv_number;
    };
}

在此class定义中

namespace ABC {
    class Bob {
        friend class Joe;
        public:
            Bob ();
            int pub_number;
        private:
            int priv_number;
    };
}

朋友 class Joe 的声明在命名空间 ABC 的范围内引入了名称 Joe 因为 class 的先前声明Joe 不可见,使用了不合格的名称。

来自 C++ 标准(10.3.1.2 命名空间成员定义)

  1. ... If the name in a friend declaration is neither qualified nor a template-id and the declaration is a function or an elaborated-type-specifier, the lookup to determine whether the entity has been previously declared shall not consider any scopes outside the innermost enclosing namespace.

您需要在 class Bob 的声明之前和 class 中的全局命名空间中放置 class Joe 的声明Bob 你必须使用朋友的合格名称 class 至少喜欢

class Joe;

namespace ABC {
    class Bob {
        friend class ::Joe;
        public:
            Bob ();
            int pub_number;
        private:
            int priv_number;
    };
}

或者您可以在命名空间 ABC 中使用 using 声明,例如

class Joe;

namespace ABC {
    using ::Joe;

    class Bob {
        friend class Joe;
        public:
            Bob ();
            int pub_number;
        private:
            int priv_number;
    };
}