C++ Fonctions amies
Laaris
-
pascal.barbier Messages postés 33 Date d'inscription Statut Membre Dernière intervention -
pascal.barbier Messages postés 33 Date d'inscription Statut Membre Dernière intervention -
Bonjour,
J'ai une question à propos des classes amies en C++ (j'ai déjà posté ça ailleurs mais ce n'était pas le bon forum, désolé pour le doublon)
Comment fait-on pour déclarer "amie" une fonction d'une autre classe sans déclarer "amie" la classe entière?
J'ai lu quelque part qu'il faut "préciser son nom complet à l'aide de l'opérateur de résolution de portée" mais qu'est-ce donc qu'un opérateur de résolution de portée?
Merci d'avance.
J'ai une question à propos des classes amies en C++ (j'ai déjà posté ça ailleurs mais ce n'était pas le bon forum, désolé pour le doublon)
Comment fait-on pour déclarer "amie" une fonction d'une autre classe sans déclarer "amie" la classe entière?
J'ai lu quelque part qu'il faut "préciser son nom complet à l'aide de l'opérateur de résolution de portée" mais qu'est-ce donc qu'un opérateur de résolution de portée?
Merci d'avance.
A voir également:
- C++ Fonctions amies
- Codes secrets Android : accéder aux fonctions cachées - Guide
- Fonctions excel en anglais - Guide
- Fonctions excel - Guide
- Fonction puissance c++ - Forum C++
- Aucun groupe de fonctions ni onglet n'est actuellement chargé dans le ruban - Forum Word
9 réponses
Bonjour
L'opérateur de résolution de portée c'est ::
Si ta fonction amie est membre d'une classe, il faut que tu la déclares amie par
friend returntype maclasse::mafonction(parametres);
Si elle n'est pas membre d'une classe, il n'y a bien sûr pas de maclasse::
L'opérateur de résolution de portée c'est ::
Si ta fonction amie est membre d'une classe, il faut que tu la déclares amie par
friend returntype maclasse::mafonction(parametres);
Si elle n'est pas membre d'une classe, il n'y a bien sûr pas de maclasse::
Dans l'exemple qui suit, la classe B se déclare "amie" de la fonction fct de la classe A. Ainsi, cette fonction pourra utiliser la partie privée de la classe B :
L'opérateur de résolution de portée est le double deux-points qui précède le nom de la méthode dans la déclaration friend. Il permet de préciser à quelle classe appartient cette fonction.
Pour plus de précisions voir :
Thinking in C++ : https://bruce-eckel.developpez.com/livres/cpp/traduction/ticpp2vol1/?vue=Comparatif&chapitre=5.3
class A { public: int fct(int a, int b); }; class B { friend int A::fct(int a, int b); private: static void f(void) {} };
L'opérateur de résolution de portée est le double deux-points qui précède le nom de la méthode dans la déclaration friend. Il permet de préciser à quelle classe appartient cette fonction.
Pour plus de précisions voir :
Thinking in C++ : https://bruce-eckel.developpez.com/livres/cpp/traduction/ticpp2vol1/?vue=Comparatif&chapitre=5.3
Si j'en crois mon manuel C++, ce problème est classique et ne peut être contourné qu'en déclarant la classe complète comme friend :
class B
{
friend class A;
private:
static void f(void) {}
};
class A
{
public:
int fct(B instance_de_B);
};
ce qui est moins propre, puisque toutes les fonctions membres de A ont maintenant accès à la partie privée de B.
class B
{
friend class A;
private:
static void f(void) {}
};
class A
{
public:
int fct(B instance_de_B);
};
ce qui est moins propre, puisque toutes les fonctions membres de A ont maintenant accès à la partie privée de B.
Deux choses :
d'abord int fct(B instance_de_B); va créer une copie temporaire de instance_de_B dans la pile. Ce qui peut avoir des effets indésirables (copy constructeur). Il vaut mieux passer une référence de instance_de_B. Si on veut garantir que cet objet ne sera pas modifié par fct (comme dans le cas d'un passage par valeur) il suffit de déclarer la référence const :
Deuxième chose :
dans la classe A si on n'utilise qu'une référence de B, il suffit de faire précéder le prototype de la classe A par la déclaration d'existance de la classe B :
d'abord int fct(B instance_de_B); va créer une copie temporaire de instance_de_B dans la pile. Ce qui peut avoir des effets indésirables (copy constructeur). Il vaut mieux passer une référence de instance_de_B. Si on veut garantir que cet objet ne sera pas modifié par fct (comme dans le cas d'un passage par valeur) il suffit de déclarer la référence const :
int fct(const B& instance_de_B);
Deuxième chose :
dans la classe A si on n'utilise qu'une référence de B, il suffit de faire précéder le prototype de la classe A par la déclaration d'existance de la classe B :
class B; class A { public: int fct(const B& instance_de_B); }; class B { friend int A::fct(int a, int b); private: static void f(void) {} };
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
Bien sur c'est une technique courante qui permet d'utiliser des pointeurs ou des références d'une classe avant d'en avoir donné le prototype détaillé.
Le compilateur n'aime pas, mais pour une autre raison, tu n'as pas mis les mêmes paramètres à A::fct dans A et dans B
Le problème dont je parle n'intervient pas ici, il se pose quand il y a des friend croisés entre deux classes :
Le problème dont je parle n'intervient pas ici, il se pose quand il y a des friend croisés entre deux classes :
class A; class B; class B { friend int A::fct(const B& instance_de_B); static void f(void) {} }; class A { friend void B::f(void); int fct(const B& instance_de_B); };
Pour la définition de la fonction fct mille excuses c'est un copier/coller trop rapide.
En ce qui concerne les friends croisés effectivement on ne peut pas s'en sortir sans déclarer une amitié de classe.
Toutefois le cas doit être très rare d'avoir à déclarer deux amitiés croisées de fonctions. Personnellement je n'ai quasiment jamais eu besoin des déclarations d'amitié. En général une petite revue d'architecture permet de trouver une solution plus pure.
En ce qui concerne les friends croisés effectivement on ne peut pas s'en sortir sans déclarer une amitié de classe.
Toutefois le cas doit être très rare d'avoir à déclarer deux amitiés croisées de fonctions. Personnellement je n'ai quasiment jamais eu besoin des déclarations d'amitié. En général une petite revue d'architecture permet de trouver une solution plus pure.
Merci pour cette info, mais un autre problème se pose.
Si je fais:
class A
{
public:
int fct(B instance_de_B);
};
class B
{
friend int A::fct(int a, int b);
private:
static void f(void) {}
};
le compilateur me dit "B has not been declared", et si je déclare B avant A, il me dit "A has not been declared"
Si je fais:
class A
{
public:
int fct(B instance_de_B);
};
class B
{
friend int A::fct(int a, int b);
private:
static void f(void) {}
};
le compilateur me dit "B has not been declared", et si je déclare B avant A, il me dit "A has not been declared"