此代码可以在 MSVC 2013 下编译,但不能在 Clang 500.2.79 下编译:
class A
{
friend class B;
B *b;
};
class B
{
};
> error: unknown type name 'B'
为什么?
最佳答案
友元声明本身并不(总是)需要前向声明,但友元指针/引用的后续使用却需要。VC++ 似乎允许语言规范不允许的功能。不过,函数的查找规则确实比类稍微宽松一些:
C++11 §7.3.1.2/3 (Namespace member definitions) [namespace.memdef]:
Every name first declared in a namespace is a member of that namespace. If a friend declaration in a non-local class first declares a class, function, class template or function template the friend is a member of the innermost enclosing namespace. The name of the friend is not found by unqualified lookup (3.4.1) or by qualified lookup (3.4.3) until a matching declaration is provided in that namespace scope (either before or after the class definition granting friendship). If a friend function or function template is called, its name may be found by the name lookup that considers functions from namespaces and classes associated with the types of the function arguments (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
关于c++ - 为什么我不能转发声明内部友元类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23704266/