6

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

在命名空间中首先声明的每个名称都是该命名空间的成员。如果非本地类中的友元声明首先声明了一个类或函数(这意味着类或函数的名称是不合格的),则友元类或函数是最内层封闭命名空间的成员。

// 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 YA::h::h

4

2 回答 2

2

在该段的末尾,它指出:

在查找声明为友元的类或函数的先前声明时,并且当友元类或函数的名称既不是限定名称也不是模板 ID 时,不考虑最内层封闭命名空间之外的范围。

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

于 2012-12-16T04:53:38.747 回答
1

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

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

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

11.3.4 朋友:

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

看 3.5.2:

当一个名称具有外部链接时,它所表示的实体可以被其他翻译单元的范围或同一翻译单元的其他范围的名称引用。

于 2012-12-16T04:06:12.137 回答