问题描述
在命名命名空间类中,我将一个类(位于全局命名空间中)声明为好友。 但是,后一类无法访问前一类的私有成员。为什么是这样?有什么办法解决吗?
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”类的任何名称空间,则代码将编译。
我试图按如下方式在Bob.h中转发声明Joe类:
class Joe; // This does nothing to help
class ::Joe // This produces compiler message "error: ‘Joe’ in namespace ‘::’ does not name a type"
解决方法
您需要在全局名称空间中添加一个无作用域的前向声明,并在声明好友时使用作用域运算符:
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;
};
}
,
您的friend
声明也需要::
前缀:
class Joe;
namespace ABC {
class Bob {
friend class ::Joe;
// ^^ here
...
};
}
,
在此类定义中
namespace ABC {
class Bob {
friend class Joe;
public:
Bob ();
int pub_number;
private:
int priv_number;
};
}
朋友类Joe
的声明在名称空间Joe
的范围内引入了名称ABC
,因为类Joe
的先前声明不可见使用了不合格的名称。
根据C ++标准(10.3.1.2命名空间成员定义)
- ...如果朋友声明中的名称不合格也不是 template-id,声明是一个函数或一个 elaborated-type-specifier,用于确定是否为实体的查找 先前已声明的内容不得考虑以下任何范围 最内层的封闭命名空间。
您需要在全局命名空间中将类Joe
的声明放在类Bob
的声明之前,并且在类Bob
中,您必须使用标准名称朋友班至少喜欢
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;
};
}