pes*_*che 46 c++ namespaces friend forward-declaration
假设我有一个类F
应该是类G
(在全局命名空间中)和C
(在命名空间中A
)的朋友.
A::C
,F
必须向前宣布.G
,没有F
必要的前瞻性声明.A::BF
可以成为朋友而A::C
无需前瞻性声明下面的代码说明了这一点,并使用GCC 4.5,VC++ 10以及至少与另一个编译器进行编译.
class G {
friend class F;
int g;
};
// without this forward declaration, F can't be friend to A::C
class F;
namespace A {
class C {
friend class ::F;
friend class BF;
int c;
};
class BF {
public:
BF() { c.c = 2; }
private:
C c;
};
} // namespace A
class F {
public:
F() { g.g = 3; c.c = 2; }
private:
G g;
A::C c;
};
int main()
{
F f;
}
Run Code Online (Sandbox Code Playgroud)
这对我来说似乎不一致.这是有原因还是只是标准的设计决定?
Ale*_*tov 45
C++
标准 ISO/IEC 14882:2003(E)
7.3.1.2命名空间成员定义
第3段
首先在名称空间中声明的每个名称都是该名称空间的成员.如果非本地类中的友元声明首先声明一个类或函数(这意味着该类或函数的名称是不合格的),那么友元类或函数是最内层封闭命名空间的成员.
Run Code Online (Sandbox Code Playgroud)// Assume f and g have not yet been defined. void h(int); template <class T> void f2(T); namespace A { class X { friend void f(X); // A::f(X) is a friend class Y { friend void g(); // A::g is a friend friend void h(int); // A::h is a friend // ::h not considered friend void f2<>(int); // ::f2<>(int) is a friend }; }; // A::f, A::g and A::h are not visible here X x; void g() { f(x); } // definition of A::g void f(X) { /* ... */} // definition of A::f void h(int) { /* ... */ } // definition of A::h // A::f, A::g and A::h are visible here and known to be friends }
您friend class BF;
是A::BF
名称空间A而不是全局名称空间的声明.您需要全局事先声明才能避免此新声明.
让我们从您的示例中考虑以下3个代码行:
1. friend class F; // it creates "friend declaration", (that's not the same as ordinary forward declaration
2. class F; // without this forward declaration, F can't be friend to A::C <-- this is ordinary forward declaration
3. friend class ::F; // this is qualified lookup (because of ::), so it needs previous declaration, which you provide in line 2.
Run Code Online (Sandbox Code Playgroud)
第7.3.1.2节中的C++标准,第3点(命名空间成员定义)说:
友元声明本身不会使名称对非限定查找(3.4.1)或限定查找(3.4.3)可见.[注意:如果在命名空间范围内提供匹配的声明(在类定义授予友谊之前或之后),则朋友的名称将在其命名空间中可见. - 尾注]
第2行完全符合标准要求.
所有的困惑都是因为"朋友宣言" 很弱,你需要提供坚实的前瞻性声明以供进一步使用.