【问题标题】:Friend function is not visible in the class好友功能在课堂上不可见
【发布时间】:2014-05-08 11:42:39
【问题描述】:

我有以下代码:

struct M {
    friend void f() {}
    M() {
        f(); // error: 'f' was not declared in this scope
    }
};

int main() {
    M m;
}

Live example

g++4.8 和 clang3.4 都无法编译它,因为 fM 中不可见,或者他们是这么说的。

但是,标准给出了类似代码的示例

class M {
  friend void f() { } // definition of global f, a friend of M,
                      // not the definition of a member function
};

然后说

类中定义的friend 函数位于 定义它的类。

(ISO/IEC 14882:2011 11.3 Friends [class.friend] p6, p7)

从这里我无法理解编译器如何找不到在使用它的同一类中定义的f

两个编译器不太可能有相同的错误。
那么,我错过了什么?

【问题讨论】:

  • 你在哪里声明的?

标签: c++


【解决方案1】:

友元声明表明,在周围命名空间中名为f 的函数是该类的友元;但它没有将名称 f 引入命名空间。在命名空间中声明之前,它是不可用的(除了依赖于参数的查找)。

相关规则为C++11 7.3.1.2/3:

如果非本地类中的friend 声明首先声明了一个类或函数,则友元类或函数是最内层封闭命名空间的成员。 在该命名空间范围内提供匹配声明之前,通过非限定查找或限定查找未找到朋友的名称

【讨论】:

    【解决方案2】:

    这句话来自 C++ 标准

    类中定义的友元函数在 定义它的类。

    意思如下

    9 名称查找用于定义友元函数的名称 (11.3) 在授予友谊的类中定义的内联应继续 如成员函数定义中的查找所述。

    即从类范围开始搜索函数中使用的任何名称。

    然而,函数本身在命名空间中是不可见的,直到它在类之外声明。

    所以在你的情况下,在类定义之前声明函数就足够了

    void f() {}
    
    struct M {
        friend void f();
        M() {
            f(); 
        }
    };
    
    int main() {
        M m;
    }
    

    或者

    void f();
    
    struct M {
        friend void f() {}
        M() {
            f(); 
        }
    };
    
    int main() {
        M m;
    }
    

    【讨论】:

    • @Kate Gregory 谢谢。由于“复制和粘贴”操作,这是一个错字。
    • @Jonathan Mee 谁允许你编辑我的帖子?!不要再这样做了!
    • Aaand...那是我的错。感谢收看。
    【解决方案3】:

    关键问题是编译器在什么情况下能够/允许找到您的函数声明。 对于一般的friend 函数,您必须在类之外声明它,以便编译器能够找到它。

    但是有一个非常有用的例外:如果friend函数有一个类类型的参数,由于argument-dependent name lookup,它可以在没有额外声明的情况下找到函数。

    这种情况实际上非常重要,因为通常您希望friend 函数访问类类型的对象。


    考虑以下示例:

    #include <iostream>
    
    struct M
    {
        friend void printI(int a) {
            std::cout << a;
        }
        friend void print(const M& m) { // friend takes object of class type!
            std::cout << "M";
        }
        void foo() {
            printI(2); // ERROR - requires declaration!
            print(*this); // OK!
        }
    };
    
    int main()
    {
        M m;
        m.foo();
        printI(2); // ERROR - requires declaration!
        print(m); // OK
    }
    

    【讨论】:

      【解决方案4】:
      struct M {
          friend void f() {}
          M() {
              f(); // error: 'f' was not declared in this scope
          }
      };
      
      int main() {
          M m;
      }
      

      上面的代码完美运行。(在 DevC++ 上试过) 也尽量不要在类内定义函数,因为它可能没有在它之外的范围,即在main() 中。 在尝试从main() 调用f() 时,您将收到一条错误消息,指出函数不存在。 因此,使用:: 运算符(如果需要)在类外部定义函数,以便从任何地方访问函数都没有问题。 Access friend function defined in class

      【讨论】:

      • 它可能在一些古老的、不兼容的编译器上“完美”地工作,但问题清楚地表明它至少不能在两个现代编译器上工作。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多