读书人

再度纠结于友元声明是否向外围引入名字

发布时间: 2012-08-27 21:21:56 作者: rapoo

再次纠结于友元声明是否向外围引入名字
C++标准:

3. A function first declared in a friend declaration has external linkage (3.5). Otherwise, the function retains its previous linkage (7.1.1).

按照3中说的,下面代码是应该通过的

C/C++ code
class X{    friend void f(); };int main(){    f(); //因为类X中的友元函数f的声明有外部链接,所以,f可见}void f() { /* ok to define friend function in the class body */ }

编译测试:
VC2005/2010通过 ,而GCC 4.4.3报错:无法找到名字f


5. A function can be defined in a friend declaration of a class if and only if the class is a non-local class (9.8),the function name is unqualified, and the function has namespace scope.
[Example:
class M {
friend void f() { } // definition of global f, a friend of M,
// not the definition of a member function
};
—end example]
Such a function is implicitly inline. A friend function defined in a class is in the (lexical) scope of the class in which it is defined. A friend function defined outside the class is not (3.4.1).

按照5中说的,既然在类中定义友元函数f,是"definition of global f",那么也就可以理解为下面的代码是可以通过编译的
C/C++ code
class X{    friend void f(){ /* ok to define friend function in the class body */ }};int main(){    f(); } 

然而VC2005/2010和GCC4.4.3都不能通过

TCPL中对友元有如下说明:
“一个友元声明不会给外围的作用域引进一个名字”
“一个友元函数或者需要在某个外围作用域里显式声明,或者以它的类或由该类派生的类作为一个参数(13.6节),否则就无法调用这个友元了。”

C++ primer有如下:
“友元声明将已命名的类或非成员函数引入到外围作用域中。此外,友元函数可以在类的内部定义,该函数的作用域扩展到包围该类定义的作用域。”
“用友元引入的类名和函数(定义或声明),可以像预先声明的一样使用”
C++ primer中的例子:
class X {
friend class Y;
friend void f() { /* ok to define friend function in the class body */ }
};
class Z {
Y *ymem; // ok: declaration for class Y introduced by friend in X
void g() { return ::f(); } // ok: declaration of f introduced by X
};



标准中说的和C++ PRIMER一样,而和TCPL不一样。
至于编译器,GCC做的和TCPL说的一样,而VC和标准说的部分一样(对于在友元声明出定义函数处有出入)

个人总结
两个编译器行为不同,所以尽量提前声明友元所声明的名字

以上只是个人的看法,如果有不对的地方,恳请各位大大指正

[解决办法]
别纠结了,凡这么需要你搬标准才能判断行为的代码,就可以认为是一种错误了。
所以,懂了又有何用。

读书人网 >C++

热点推荐