繁体   English   中英

为什么我不能转发声明内部朋友课程?

[英]Why can't I forward declare an internal friend class?

此代码在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.memdef]

名称空间中第一个声明的每个名称都是该名称空间的成员。 如果非本地类中的朋友声明首先声明了一个类,函数,类模板或函数模板,则该朋友是最内层的封闭命名空间的成员。 直到通过在名称空间范围中提供匹配的声明(在授予友谊的类定义之前或之后),才可以通过不合格的查找(3.4.1)或合格的查找(3.4.3)找不到朋友的名称。 如果调用了朋友函数或函数模板 ,则可以通过名称查找来找到其名称,该名称查找考虑了来自与函数参数类型相关联的名称空间和类中的函数(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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM