为什么我不能转发申报内部朋友类?

时间:2014-05-16 20:44:41

标签: c++ friend

此代码在MSVC 2013下编译,但不在Clang 500.2.79下编译:

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

class B
{
};

> error: unknown type name 'B'

为什么?

1 个答案:

答案 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