考虑一个命名空间中的类。类的定义声明了一个友元函数。
namespace Foo
{
class Bar
{
friend void baz();
};
}
据我所知,这应该将 baz()
声明为最内层封闭命名空间的成员,即 Foo
。
因此,我希望 baz()
的以下定义是正确的:
void Foo::baz() { }
但是,GCC (4.7) 给我一个错误。
error: ‘void Foo::baz()’ should have been declared inside ‘Foo’
几个解决方案似乎有效:
在类外声明
baz()
。namespace Foo { void baz(); class Bar { friend void baz(); }; }
在命名空间内定义
baz()
。namespace Foo { class Bar { friend void baz(); }; } ... namespace Foo { void baz() { } }
使用
-ffriend-injection
标志进行编译,这消除了错误。
这些解决方案似乎与我所知道的 C++ 中声明/定义的一般规则不一致。
为什么我必须声明 baz()
两次?
为什么定义仅在命名空间内合法,而在范围解析运算符中非法?
为什么flag会消除错误?
最佳答案
Why do I have to declare baz() twice?
因为友元声明没有在命名空间中提供可用的函数声明。它声明,如果该函数在该命名空间中声明,它将成为友元;并且如果您要在类中定义一个友元函数,那么它就可以通过参数相关的查找(而不是其他方式)获得,就好像它是在命名空间中声明的一样。
Why is the definition otherwise only legal inside a namespace, and illegal with the scope resolution operator?
因为它没有在命名空间中(正确地)声明,并且如果函数已经声明,则只能在其命名空间之外定义(具有范围解析)。
Why does the flag eliminate the error?
因为标志使友元声明充当命名空间中的声明。这是为了与 C++ 的古代方言(显然还有一些现代编译器)兼容,在这些方言中这是标准行为。
关于c++ - 命名空间内的友元函数声明/定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16718166/