朋友宣言没有向前宣布

Jar*_*edC 7 c++ c++11

我的理解是,friend如果使用了class说明符,声明也可以作为类的前向声明,如下例所示:

class A
{
    friend class B;
    B* b;
};

class B {};

int main() {}
Run Code Online (Sandbox Code Playgroud)

但是,g ++(4.6.3和4.7.0)给出了以下错误(g ++ - 4.7应该支持扩展好友声明),这是没有前向声明的预期:

main.cpp:6:2:错误:'B'没有命名类型

为了证实我friend class B;应该作为前瞻性声明的期望,我找到了这个答案这个答案,但两者都没有结论(或者至少我不能从中得出很多结论)所以我试图查阅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-speci?er declares new class
}
Run Code Online (Sandbox Code Playgroud)

基于我对第三个声明的阅读,我friend class B应该是一个精心设计的类型说明符,声明一个新的类.

我刚刚开始理解官方的标准措辞,所以我必须遗漏一些东西.我有什么误会?

asc*_*ler 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
}
Run Code Online (Sandbox Code Playgroud)


K-b*_*llo 5

您的friend class B;声明确实用作前向声明,但在提供匹配声明之前,不会通过名称查找找到此声明.

[class.friend]/11:

如果友元声明出现在本地类(9.8)中并且指定的名称是非限定名称,则会查找先前声明,而不考虑最内部封闭非类作用域之外的作用域.对于朋友函数声明,如果没有事先声明,则程序格式错误.对于友元类声明,如果没有先前的声明,则指定的类属于最内层的封闭非类范围,但如果随后引用它,则在提供匹配的声明之前,不会通过名称查找找到其名称.最内层的非类范围.