命名空间中的C ++前向声明和友谊

时间:2012-12-16 02:22:55

标签: c++ namespaces friend access-control forward-declaration

根据7.3.1.2 C ++标准ISO / IEC 14882:2003(E)中的命名空间成员定义

  

首先在名称空间中声明的每个名称都是其中的一员   命名空间。如果非本地类中的朋友声明首先声明   一个类或函数(这意味着类的名称或   函数不合格)朋友类或函数是其成员   最里面的封闭命名空间。

// Assume f and g have not yet been defined.
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
}

由于void h(int);首先在全局命名空间中声明,因此它是全局命名空间的成员。为什么friend void h(int);中的朋友声明class Y会考虑A::h而不是::h

2 个答案:

答案 0 :(得分:2)

在该段末尾,它指出:

  

当查找声明为朋友的类或函数的先前声明时,以及友元类或函数的名称既不是限定名称也不是模板ID时,不考虑最内层封闭命名空间之外的作用域

这就是不考虑::h的原因:它既不是限定名,也不是模板ID。这也是考虑':: f2`的原因,因为它是模板ID。

答案 1 :(得分:1)

我认为内部声明会影响全局命名空间中的声明。此外,朋友声明本身是前向声明,因此它们会影响全局命名空间中的声明,而不仅仅是“引用”这些函数。

参考N3485中的3.3.10.1“名字隐藏”:

  

可以通过在a中明确声明同名来隐藏名称   嵌套声明性区域或派生类(10.2)。

11.3.4朋友:

  

首先在朋友声明中声明的函数具有外部链接   (3.5)。否则,该函数将保留其先前的链接(7.1.1)。

看3.5.2:

  

当名称具有外部链接时,它表示的实体可以是   来自其他翻译单位范围的名称或来自   同一翻译单位的其他范围。