【问题标题】:Looking for a prior declaration, introduced by friend declaration找事先声明,朋友介绍的声明
【发布时间】:2014-05-28 08:28:38
【问题描述】:

有一句引自 3.4.1/7:

在查找引入的类或函数的先前声明时 通过朋友声明,范围在最里面的封闭之外 不考虑命名空间范围;

你能举个例子来说明这个规则吗?

【问题讨论】:

  • cppreference 的Name Lookup 部分对此以及许多其他有趣的查找条件有相当可靠的描述。值得一读。

标签: c++ namespaces friend


【解决方案1】:

当然。此代码有效(两个类都在同一个命名空间中):

namespace Foo {
  class Bar
  {
  friend class FooBar;
  public:
    Bar() : i(0){}
  private:
    int i;
  };

  class FooBar
  {
    FooBar( Bar & other )
    {
      other.i = 1;
    }
  };
}//namespace Foo

并且此代码失败(朋友类在Foo 的封闭命名空间之外,因此查找失败并且您会看到int Foo::i is private within this context 错误):

namespace Foo {
  class Bar
  {
  friend class FooBar;
  public:
    Bar() : i(0){}
  private:
    int i;
  };
}//namespace Foo

class FooBar
{
    FooBar( Foo::Bar & other )
    {
        other.i = 1;//Oops :'(
    }
};

【讨论】:

    【解决方案2】:

    此规则规定编译器在哪里寻找标记为friend 的函数或类。它规定,编译器将只检查与允许friend 访问的类在同一命名空间中的函数或类。它不会检查其他或外部命名空间中的函数或类。


    这段代码会产生错误:

    #include <iostream>
    
    namespace a {
      class Q { int x; friend void foo(Q q); };
    }
    
    // function foo is in outer namespace (not in a)
    void foo(a::Q q) { std::cout << q.x << std::endl; }
    //                              ^^^ ERROR q.x is private
    
    int main() {
        a::Q q;
        foo(q);
    }
    

    原因是函数foo 不在命名空间a 中,而是在外部命名空间(在本例中为全局命名空间)。因此fooQ 中的朋友声明不匹配。


    此代码将起作用:

    #include <iostream>
    
    namespace a {
      class Q { int x; friend void foo(Q q); };
    }
    
    // function foo is in same namespace as Q
    namespace a {
      void foo(Q q) { std::cout << q.x << std::endl; }
    //                            ^^^ OK access allowed by friend
    }
    
    int main() {
        a::Q q;
        a::foo(q);
    }
    

    这是可行的,因为函数 foo 现在与 Q 在同一个命名空间中。因此foo 匹配Q 中的朋友声明。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-04
      • 1970-01-01
      相关资源
      最近更新 更多