根据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
?
答案 0 :(得分:2)
在该段末尾,它指出:
当查找声明为朋友的类或函数的先前声明时,以及友元类或函数的名称既不是限定名称也不是模板ID时,不考虑最内层封闭命名空间之外的作用域
这就是不考虑::h
的原因:它既不是限定名,也不是模板ID。这也是考虑':: f2`的原因,因为它是模板ID。
答案 1 :(得分:1)
我认为内部声明会影响全局命名空间中的声明。此外,朋友声明本身是前向声明,因此它们会影响全局命名空间中的声明,而不仅仅是“引用”这些函数。
参考N3485中的3.3.10.1“名字隐藏”:
11.3.4朋友:可以通过在a中明确声明同名来隐藏名称 嵌套声明性区域或派生类(10.2)。
首先在朋友声明中声明的函数具有外部链接 (3.5)。否则,该函数将保留其先前的链接(7.1.1)。
看3.5.2:
当名称具有外部链接时,它表示的实体可以是 来自其他翻译单位范围的名称或来自 同一翻译单位的其他范围。