此代码在MSVC 2013下编译,但不在Clang 500.2.79下编译:
class A
{
friend class B;
B *b;
};
class B
{
};
> error: unknown type name 'B'
为什么?
答案 0 :(得分:4)
朋友声明本身(总是)不需要前向声明,但后续使用友情指针/引用会这样做。 VC ++似乎允许语言规范不允许的功能。函数确实具有比类更自由的查找规则:
C ++11§7.3.1.2/ 3 (命名空间成员定义) [namespace.memdef] :
首先在名称空间中声明的每个名称都是该名称空间的成员。如果非本地类中的朋友声明首先声明了类,函数,类模板或函数模板,则该朋友是最内层封闭命名空间的成员。在该命名空间范围内(在授予友谊的类定义之前或之后)提供匹配声明之前,通过不合格的查找(3.4.1)或限定查找(3.4.3)找不到朋友的姓名。如果调用朋友功能或功能模板,则为其 name可以通过名称查找找到,该名称查找考虑名称空间中的函数和与函数参数类型相关联的类(3.4.2)。
规范的示例:
// Assume f and g have not yet been declared.
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
}
using A::x;
void h() {
A::f(x);
A::X::f(x); // error: f is not a member of A::X
A::X::Y::g(); // error: g is not a member of A::X::Y
}
内部(“嵌套”)类是自动结合的,但它们必须在内部定义,而不仅仅是声明:
class A {
public:
// This class is nested, and referred to as "A::B" outside of A.
class B {
public:
int foo(A &a) { return a.x; } // OK by default to access A's privates
};
private:
int x;
};
A a;
A::B b;
int n = b.foo(a);
如果你移动你的B定义(或只是做一个前向声明),你可以正确地告诉非嵌套类:
class B;
class A {
friend class B; // OK, since B (not nested) declared before this directive
B *b;
}
class B { }; // can define B later, since only B pointer/references used earlier