29 votes

Accès à la fonction amie définie dans la classe

Il existe un tel code :

#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
} 

Comment accéder à la fonction fun2() ?

26voto

Lightness Races in Orbit Points 122793
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();
};

Bien que votre définition de fun2 hace définit une fonction " globale " plutôt qu'un membre, et en fait une friend de A en même temps, il manque toujours une déclaration de la même fonction dans la portée globale elle-même.

Cela signifie qu'aucun code dans cette portée n'a la moindre idée que fun2 existe.

Le même problème se pose pour fun sauf que la fonction Argument-Dependent Lookup peut prendre le relais et trouver la fonction, car il y a un argument de type A .

Je recommande plutôt de définir vos fonctions de la manière habituelle :

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();

Remarquez maintenant que tout travaux (sauf fun3 car je ne l'ai jamais défini).

16voto

Charles Bailey Points 244082

La raison pour laquelle vous pouvez appeler fun est que la déclaration d'ami dans la classe A le rend visible uniquement via une recherche dépendante de l'argument. Sinon, les déclarations d'amis ne rendent pas les fonctions qu'elles déclarent automatiquement visibles en dehors de la portée de la classe où elles apparaissent.

Vous devez ajouter une déclaration à la portée de l'espace de nom ou à l'intérieur de main de faire fun2 visible dans main .

Par exemple

void fun2();

fun3 est visible à l'intérieur main parce que sa définition (en dehors de la classe) est également une déclaration qui le rend visible à partir de main .

ISO/IEC 14882:2011 7.3.1.2 :

Le nom de l'ami n'est pas trouvé par une recherche non qualifiée (3.4.1) ou par une recherche qualifiée (3.4.3) jusqu'à ce qu'une déclaration correspondante soit fournie dans la portée de cet espace de nom (soit avant ou après la définition de la classe accordant l'amitié).

3.4.2 (Recherche de nom dépendant d'un argument) / 4 :

Les fonctions amies ou les modèles de fonctions amies déclarés dans les classes associées sont visibles dans leurs espaces de noms respectifs même si elles ne sont pas visibles lors d'une recherche ordinaire (11.3).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X