C++;命名空间中的转发声明和友谊 >在C++标准ISO/IEC 1488~2003(E)中7.3.1.2命名空间成员定义
名称空间中首先声明的每个名称都是该名称空间的成员 命名空间。如果非本地类中的友元声明首先声明 类或函数(这意味着类或函数的名称 函数不合格)友元类或函数是 最里面的封闭命名空间C++;命名空间中的转发声明和友谊 >在C++标准ISO/IEC 1488~2003(E)中7.3.1.2命名空间成员定义,c++,namespaces,friend,access-control,forward-declaration,C++,Namespaces,Friend,Access Control,Forward Declaration,名称空间中首先声明的每个名称都是该名称空间的成员 命名空间。如果非本地类中的友元声明首先声明 类或函数(这意味着类或函数的名称 函数不合格)友元类或函数是 最里面的封闭命名空间 //假设f和g尚未定义。 空h(int); 模板空隙f2(T); 名称空间A{ X类{ 朋友void f(X);//A::f(X)是朋友 Y类{ 朋友void g();//A::g是朋友 friend void h(int);//A::h是朋友 //::h未考虑 朋友空f2(int);/::f2(int)是朋友 }; }
//假设f和g尚未定义。
空h(int);
模板空隙f2(T);
名称空间A{
X类{
朋友void f(X);//A::f(X)是朋友
Y类{
朋友void g();//A::g是朋友
friend void h(int);//A::h是朋友
//::h未考虑
朋友空f2(int);/::f2(int)是朋友
};
};
//A::f、A::g和A::h在此处不可见
X;
void g(){f(x);}//A::g的定义
void f(X){/*…*/}//A::f的定义
void h(int){/*…*/}//A::h的定义
//A::f、A::g和A::h在这里可见,并且被认为是朋友
}
因为
void h(int)
首先在全局命名空间中声明,它是全局命名空间的成员。为什么朋友声明朋友无效h(int)代码> <代码>类y>代码>考虑<代码>::h < />代码>而不是<代码>::h < /代码> < p>我认为内部声明在全局命名空间中隐藏了这些声明。而且,友元声明本身是前向声明,因此它们隐藏了全局命名空间中的声明,而不仅仅是“引用”这些函数
参考N3485中的3.3.10.1“名称隐藏”:
一个名称可以通过一个相同名称的显式声明隐藏在
嵌套的声明性区域或派生类(10.2)
11.3.4朋友:
首先在友元声明中声明的函数具有外部链接
(3.5). 否则,该功能将保留其先前的链接(7.1.1)
查看3.5.2:
当名称具有外部链接时,它所表示的实体可以是
从其他翻译单位的范围或从
同一翻译单位的其他范围
该段末尾指出:
当查找声明为友元的类或函数的先前声明,并且友元类或函数的名称既不是限定名也不是模板id时,不考虑最内层封闭命名空间之外的作用域
这就是为什么不考虑::h
:它既不是限定名,也不是模板id。这也是为什么考虑“::f2”,因为它是模板id。您只是在类X上声明了一个无效的朋友。如果它做了任何其他事情,我会担心。前面声明的void h(int)在全局中,但Y显然在命名空间A中。
// 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
}