访问在类中定义的友元函数

scd*_*dmb 41 c++ friend

有这样的代码:

#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
} 
Run Code Online (Sandbox Code Playgroud)

如何访问fun2()函数?

Lig*_*ica 35

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();
};
Run Code Online (Sandbox Code Playgroud)

虽然你的定义fun2 确实定义了一个"全球性"的功能,而不是一个成员,并使它成为friendA同时,仍然丢失了一些在全球范围内本身相同功能的声明.

这意味着该范围内的任何代码都不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();
Run Code Online (Sandbox Code Playgroud)

现在请注意,一切正常(除非fun3因为我从未定义过).


CB *_*ley 22

您可以调用的原因fun是类中的友元声明A仅通过参数依赖查找使其可见.否则,友元声明不会使它们声明的函数在出现的类范围之外自动可见.

您需要在命名空间范围或内部添加声明main以使其fun2可见main.

例如

void fun2();
Run Code Online (Sandbox Code Playgroud)

fun3在内部是可见的,main因为它的定义(在类之外)也是一个使它可见的声明main.

ISO/IEC 14882:2011 7.3.1.2:

在非命名查找(3.4.1)或限定查找(3.4.3)之前找不到朋友的名称,直到在该命名空间范围内提供匹配声明(在授予友谊的类定义之前或之后).

3.4.2(依赖于参数的名称查找)/ 4:

在关联类中声明的任何命名空间范围的朋友函数或友元函数模板在其各自的命名空间中都是可见的,即使它们在普通查找期间不可见(11.3).