我有以下代码:
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都无法编译它,因为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
,这是在同一个类中定义的,它的使用。
两个编译器不太可能有相同的bug。
我错过了什么
4条答案
按热度按时间x6yk4ghg1#
友元声明声明周围命名空间中名为
f
的函数是类的友元;但是它没有将名称f
引入到名称空间中。在命名空间中声明它之前,它是不可用的(除了依赖于参数的查找)。相关规则是C++11 7.3.1.2/3:
如果非局部类中的
friend
声明首先声明了一个类或函数,则友元类或函数是最内层封闭命名空间的成员。**通过非限定查找或限定查找,**无法找到朋友的名字,直到在该命名空间范围内提供匹配的声明。gv8xihay2#
关键的问题是在什么情况下编译器能够/允许找到你的函数声明。对于一个通用的
friend
函数,你必须在类的外部声明它,这样编译器才能找到它。但有一个非常有用的例外:如果
friend
函数有一个类类型的参数,由于argument-dependent name lookup,它可以在没有额外声明的情况下找到该函数。这种情况实际上非常重要,因为通常您希望
friend
函数访问类类型的对象。请考虑以下示例:
ttvkxqim3#
C++标准中的这句话
在类中定义的友元函数在定义它的类的(词法)作用域中。
意味着以下
9在授予友谊的类中内联定义的朋友函数(11.3)的定义中使用的名称的名称查找应按照成员函数定义中的查找所述进行。
也就是说,从类作用域开始搜索函数中使用的任何名称。
但是,函数本身在命名空间中不可见,直到它在类外部声明。
所以在你的例子中,在类定义之前声明函数就足够了
或
olmpazwi4#
上面的代码工作得很好。(在DevC++上尝试)也尽量不要在类内部定义函数,因为它可能没有外部作用域,即。在
main()
中。在尝试从main()
调用f()
时,您将收到一个错误,说函数不存在。因此,使用::
操作符(如果需要)在类外部定义函数,以便从任何地方访问函数都没有问题。Access friend function defined in class