友元声明不是前向声明

8

据我理解,如果使用class限定符,friend声明也可以作为类的前向声明,例如:

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

class B {};

int main() {}

然而,g++(4.6.3和4.7.0)给出了以下错误(g++-4.7应该支持扩展友元声明),如果没有前向声明,则会出现这种情况:

main.cpp:6:2: error: ‘B’ does not name a type

为了确认我的期望,即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-specifier declares new class
}

根据我对第三个声明的阅读,我的friend class B应该是一个用于声明新类的详细类型说明符

我刚开始理解官方标准措辞,所以可能有些地方没看懂。请问我哪里有误解?

2个回答

7

请看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
}

7
您的 friend class B; 声明确实可以作为前向声明,但是在提供匹配声明之前,该声明不会通过名称查找找到。
[class.friend]/11:
如果友元声明出现在本地类 (9.8) 中,并且指定的名称是未限定名称,则会查找先前的声明,而不考虑超出最内层封闭非类作用域的范围。对于友元函数声明,如果没有先前的声明,则程序无效。对于友元类声明,如果没有先前的声明,则指定的类属于最内层封闭的非类作用域,但是如果随后引用它,则其名称直到在最内层封闭的非类作用域中提供匹配的声明时才能找到。

不,真的是::B:http://ideone.com/bEgZrq。注意“最内层的封闭*非类*作用域”。 - aschepler
@K-ballo 所以,当它说声明了一个新类时,这仅仅是为了friend声明的目的,而不是其他任何东西的利益吗? - JaredC
@K-ballo,那就是我困惑的地方了。我以为“声明”意味着它也将名称引入作用域,并忽略了“在提供匹配声明之前,其名称不会被名称查找找到”的部分。 - JaredC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接