Функция доступа к другу, определенная в классе
Существует такой код:
#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()?
Ответы
Ответ 1
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
of A
, вам все равно не хватает декларации той же функции в самой глобальной области.
Это означает, что никакой код в этой области не имеет представления о существовании fun2
.
То же самое происходит и для fun
, за исключением того, что поиск аргументов зависит от функции, потому что есть аргумент типа 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();
Обратите внимание, что все работает (кроме fun3
, потому что я никогда не определял его).
Ответ 2
Причина, по которой вы можете вызвать fun
, заключается в том, что объявление друга внутри класса A
делает его видимым только с помощью зависимого от аргумента поиска. В противном случае объявления друзей не делают функции, которые они объявляют автоматически видимыми вне области класса, где они появляются.
Вам нужно добавить объявление в область пространства имен или внутри main
, чтобы сделать fun2
видимым в main
.
например.
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).