我的理解是,如果使用friend
说明符,class
声明也可以作为类的前向声明,如下例所示:
class A
{
friend class B;
B* b;
};
class B {};
int main() {}
然而,g ++(4.6.3和4.7.0)给出了以下错误(g ++ - 4.7应该支持extended friend declarations),这是没有前向声明的预期:
main.cpp:6:2:错误:'B'没有命名类型
为了确认我对friend class B;
应该作为前瞻性声明的期望,我找到this answer和this answer,但两者都没有结论(或者我不能得出多少结论)至少从他们那里)所以我试图参考c ++ 11标准并找到了这个例子:
class X2 {
friend Ct; // OK: class C is a friend
friend D; // error: no type-name D in scope
friend class D; // OK: elaborated-type-specifier declares new class
}
根据我对第三个声明的阅读,我的friend class B
应该是一个详细说明类型说明符,声明一个新类。
我刚刚开始理解官方的标准措辞,所以我必须遗漏一些东西。我误解了什么?
答案 0 :(得分:6)
看看11.3第11段:
对于友元类声明,如果没有先前的声明,则指定的类属于最内层的封闭非类范围,但如果随后引用它,则在匹配声明之前,通过名称查找找不到其名称在最里面的封闭非类范围内提供。
示例:
class X;
void a();
void f() {
class Y;
extern void b();
class A {
friend class X; // OK, but X is a local class, not ::X
friend class Y; // OK
friend class Z; // OK, introduces local class Z.
friend void a(); // error, ::a is not considered
friend void b(); // OK
friend void c(); // error
};
X *px; // OK, but ::X is found
Z *pz; // error, no Z is found
}
答案 1 :(得分:5)
您的friend class B;
声明 作为转发声明,但在提供匹配声明之前,名称查找无法找到此声明。
[class.friend] / 11 :
如果友元声明出现在本地类(9.8)中且指定的名称是非限定名称,则会查找先前声明,而不考虑最内部封闭非类作用域之外的作用域。对于朋友函数声明,如果没有事先声明,则程序格式错误。对于友元类声明,如果没有先前的声明,则指定的类属于最里面的封闭 非类范围,但如果随后引用它,则在最内层的封闭非类范围内提供匹配的声明之前,不会通过名称查找找到其名称。