类无法与不在其命名空间中的函数交朋友

Class unable to make friends with a function that's not in its namespace

本文关键字:命名空间 函数 交朋友      更新时间:2023-10-16

我很难理解为什么以下MWE没有编译:

#include <iostream>
namespace N
{
    class Foo
    {
        friend void bar( Foo& f );
        void print(){ std::cout << "..." << std::endl; }    // private by default
    };  
}
void bar( N::Foo& f )
{
    f.print();
}
int main()
{
}

g++4.8.2错误

Test.cpp: In function ‘void bar(N::Foo&)’:
Test.cpp:8:8: error: ‘void N::Foo::print()’ is private
   void print(){ std::cout << "..." << std::endl; } // private by default
        ^
Test.cpp:14:10: error: within this context

我几乎肯定在这里遗漏了一些东西,但朋友函数bar()可以访问类N::Foo的任何私有成员。

注意:

  1. 将CCD_ 3移动到名称空间CCD_
  2. 如果::bar()不调用N::Foo::print(),则代码编译

为什么代码不按原样编译?

编辑

仔细想想,这个问题的标题并没有准确地描述这个问题。我会在适当的时候编辑它。

非限定友元声明指的是包含该类的命名空间中的函数,如果尚未声明,则将该函数引入命名空间。

我会将函数移到名称空间中。它可以通过依赖于参数的查找找到,因此可以使用不合格的bar(foo)调用它,而不需要N::

如果出于某种原因您确实希望它位于全局命名空间中,那么您需要在全局命名空间中声明它,然后才能将其声明为朋友。这有点混乱:

// Need the class definition to declare the function
namespace N {class Foo;}
// Need the function definition to declare it a friend
void bar( N::Foo& );
// Need the class definition to define the function
namespace N
{
    class Foo
    {
        friend void ::bar( Foo& f );
        void print(){ std::cout << "..." << std::endl; }    // private by default
    };  
}
// And finally the function
void bar( N::Foo& f )
{
    f.print();
}