有这样的代码:
#include <iostream>
class A{
public:
friend void fun(A a){std::cout << "Im here" << std::endl;}
friend void fun2(){ std::cout << "Im here2" << std::endl; }
friend void fun3();
};
void fun3(){
std::cout << "Im here3" << std::endl;
}
int main()
{
fun(A()); // works ok
//fun2(); error: 'fun2' was not declared in this scope
//A::fun2(); error: 'fun2' is not a member of 'A'
fun3(); // works ok
}
如何访问fun2()函数?
答案 0 :(得分:34)
class A{
public:
friend void fun(A a){std::cout << "Im here" << std::endl;}
friend void fun2(){ std::cout << "Im here2" << std::endl; }
friend void fun3();
};
虽然您对fun2
的定义定义了“全局”功能而不是成员,但同时使friend
成为A
,你仍然缺少全局范围内相同功能的声明。
这意味着该范围内的任何代码都不知道fun2
存在。
fun
也出现同样的问题,但Argument-Dependent Lookup可以接管并找到该函数,因为有一个A
类型的参数。
我建议您以通常的方式定义您的功能:
class A {
friend void fun(A a);
friend void fun2();
friend void fun3();
};
void fun(A a) { std::cout << "I'm here" << std::endl; }
void fun2() { std::cout << "I'm here2" << std::endl; }
void fun3();
现在请注意everything works(fun3
除外,因为我从未定义过它)。
答案 1 :(得分:22)
您可以调用fun
的原因是类A
中的友元声明仅通过参数依赖查找使其可见。否则,友元声明不会使它们声明的函数在出现的类范围之外自动可见。
您需要在命名空间范围或main
内添加声明,以便fun2
中显示main
。
E.g。
void fun2();
fun3
在main
中可见,因为它的定义(在类之外)也是一个声明,使其在main
中可见。
ISO / IEC 14882:2011 7.3.1.2:
通过非限定查找(3.4.1)或限定查找(3.4.3)找不到朋友的名称,直到在该命名空间范围内提供匹配声明(在类定义授予友谊之前或之后)。
3.4.2(依赖于参数的名称查找)/ 4:
在关联类中声明的任何命名空间范围的朋友函数或友元函数模板在其各自的命名空间中都是可见的,即使它们在普通查找期间不可见(11.3)。