c++ - 命名空间内的友元函数声明/定义

标签 c++ namespaces friend-function

考虑一个命名空间中的类。类的定义声明了一个友元函数。

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/

相关文章:

c++ - 如何处理不使用命名空间的库

c++ - Visual Studio 2010 中的多个版本的源文件?

c++ - iOS原生sdk导入QT库

java - DOM4J xpath-选择带有命名空间的冒号节点

c++ - 使用类和友元函数的链表 : segmentation fault

c++ - 友元函数访问静态库中定义的类的私有(private)成员

c++ - 你会在哪里使用友元函数与静态成员函数?

c++ - 如何重新定义 glm 矩阵变量或删除其变换?

c++ - 对于相互转换的类型,有没有办法绕过 "deduced conflicting types for parameter in template instantiation"?

c++ - 枚举,命名空间和命名空间之外的声明导致 "call of overloaded (...) is ambiguous"