代码之家  ›  专栏  ›  技术社区  ›  msc

为什么我们不能在局部类中定义友元函数?

  •  3
  • msc  · 技术社区  · 7 年前

    我有以下c++代码片段。在内部声明了类 main() 作用

    为什么我们不能在局部类中定义友元函数?

    #include<iostream>
    
    int main()
    {
        class Foo
        {
            void foo() {} // Ok
            friend void Bar(){}; // Error
        };
    }
    
    3 回复  |  直到 7 年前
        1
  •  5
  •   StoryTeller - Unslander Monica    7 年前

    这是一个实际的原因。首先,通过限定或非限定查找都无法找到内联好友定义。它只能由ADL发现。因此,如果我们从您的示例中获取该类,请将其放在全局范围内,并尝试调用 Bar :

    class Foo
    {
        friend void Bar(){};
        void foo() {
          Bar();
        }
    };
    

    我们会得到通知 酒吧 未在该范围内声明。如果是在当地的课堂上。你不能从会员那里打电话。不能在函数内部调用它。你唯一的方法 也许 这包括一些篮球或日常生活能力。所以语言就是不允许这样。这被认为不是一个有用的功能。

        2
  •  2
  •   AnT stands with Russia    6 年前

    这没有令人信服的技术原因。你说ADL找不到?这基本上是问题的一部分: 为什么? ADL找不到吗?只要扩展ADL,让它找到它。

    这种限制的一个设计级原因可能源于友元声明中对非限定名称的语言处理。

    本地类中友元声明中使用的非限定名称引用 最近的封闭非类作用域 . 这种对非限定名称的处理非常重要,因为这是本地类相互引用的唯一方式(因为很明显,本地类没有 有资格的 姓名)

    int main()
    {
      class B;
    
      class A {
        int x;
        friend B; // refers to local `B`
      };
    
      class B {
        void foo(A &a) { a.x = 42; }
      };
    }
    

    此规则也适用于朋友 作用 具有非限定名称的声明。C++没有本地函数,但这样的友元声明仍然可以引用函数的本地非定义声明(这是完全合法的)

    void foo() {}
    
    int main()
    {
      void foo(); // refers to `::foo`
    
      class A {
        friend void foo(); // refers to local `foo`, which is `::foo`
      };
    }
    

    现在,如果有人 定义 本地类中的友元函数(当然使用非限定名称)?这种声明引入了什么功能?具体到什么范围?根据定义,它不是类的成员,因为友元声明不引入类成员。它不能是最近的封闭局部作用域的成员,因为这将使其成为 本地功能 C++不支持局部函数。

    我们不能仅仅统一地改变友元声明中所有非限定名称的行为,并说它们现在应该引用最近的封闭 命名空间 范围,因为这样就无法引用本地类(如上所示)。

    摆脱这种局面的唯一办法是 类内友元函数定义 请参考(并定义)最近封闭中的函数 命名空间 范围这样的函数只能通过[修改的]ADL调用(假设我们对此没有意见)。但这意味着我们必须在friend函数中对非限定名称给予不同的处理 定义 (与未定义的友人声明相反)。这将是相当不雅和令人困惑的。因此,语言作者决定反对它。

    注意,在C++14之后,这一点的重要性可能会显著增加,这给了我们 auto 函数中的返回类型。从那以后,当地的阶级甚至不像过去那样“当地化”

    auto foo() 
    {
      struct S // Local class
      {
        void bar() {}
      };
    
      return S();
    }
    
    int main() 
    {
      auto a = foo();
      a.bar(); // An object of local class used outside of its original scope
    
      typedef decltype(a) S; // Local type is "stolen" from its original scope
      S b;                   // and used to freely declare objects in a completely
      b.bar();               // different scope 
    }
    
        3
  •  0
  •   msc    7 年前

    因为局部类的成员函数必须完全在类体中定义,而友元函数不是成员函数。我们在类内声明友元函数,在类外定义友元函数。

    根据 cppreference :

    本地类

    • 本地类不能有静态成员
    • 局部类的成员函数没有链接
    • 局部类的成员函数必须完全在类体内定义
    • 闭包类型以外的局部类(因为C++14)不能有成员模板
    • 本地类不能有好友模板
    • 本地类无法在类定义中定义友元函数
    • 函数(包括成员函数)中的本地类可以访问封闭函数可以访问的相同名称。