簡體   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