【问题标题】:Class unable to make friends with a function that's not in its namespace类无法与不在其命名空间中的函数交朋友
【发布时间】:2014-10-31 15:23:02
【问题描述】:

我很难理解为什么以下 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. bar() 移动到命名空间 N 可解决此错误。
  2. 如果::bar() 不调用N::Foo::print(),则代码编译

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

编辑

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

【问题讨论】:

  • 为什么你认为这是一个错误? (我假设您故意说“错误”而不是“错误”。)
  • 注意点。已编辑将“错误”一词替换为“错误”。

标签: c++ namespaces argument-dependent-lookup


【解决方案1】:

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

我会将函数移到命名空间中。它可以通过依赖于参数的查找找到,因此您可以使用不合格的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();
}

【讨论】:

  • 我正要发同样的东西!
  • +1,同样,如果你要为不在当前命名空间中的东西加好友,编译器需要知道它在加好友之前驻留在哪里。这不仅限于功能。
  • 哈哈,我也是。实际上,只是尝试使用:: 来限定友元函数声明就显示了问题以及为什么它在这种情况下不起作用:Live on Coliru。因此,非限定友元声明函数声明。
猜你喜欢
  • 2010-12-29
  • 2011-09-12
  • 2016-12-27
  • 2018-06-24
  • 2018-10-20
  • 2020-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多