Friend 函数在类中不可见

问题描述 投票:0回答:4

我有以下代码:

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

int main() {
    M m;
}

实例

g++4.8和clang3.4都无法编译它,因为

f
M
内部不可见,或者他们是这么说的。

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

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++ scope friend-function
4个回答
12
投票

友元声明指出周围命名空间中名为

f
的函数是该类的友元;但它没有将名称
f
引入命名空间。在命名空间中声明它之前,它不可用(除了通过参数相关的查找)。

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

如果非本地类中的

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


4
投票
关键问题是在什么情况下编译器能够/允许找到你的函数声明。 对于一般的

friend

 函数,您必须在类之外声明它,以便编译器能够找到它。

但是有一个非常有用的例外:如果

friend

 函数具有类类型的参数,则由于
依赖于参数的名称查找,它无需额外声明即可找到该函数。

这种情况实际上非常重要,因为通常您需要一个

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
投票
引用自 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; }
    

-4
投票
struct M { friend void f() {} M() { f(); // error: 'f' was not declared in this scope } }; int main() { M m; }

上面的代码完美运行。(在DevC++上尝试过) 也尽量不要在类内部定义函数,因为它可能没有外部范围,即在

main()

 中。
在尝试从 
f()
 调用 
main()
 时,您将收到一条错误消息,指出函数不存在。
因此,使用 
::
 运算符(如有必要)在类外部定义函数,以便从任何地方访问该函数都没有问题。
访问类中定义的友元函数

© www.soinside.com 2019 - 2024. All rights reserved.