C++ Fonctions amies
Fermé
Laaris
-
8 déc. 2007 à 10:47
pascal.barbier Messages postés 33 Date d'inscription samedi 8 décembre 2007 Statut Membre Dernière intervention 7 décembre 2008 - 8 déc. 2007 à 17:32
pascal.barbier Messages postés 33 Date d'inscription samedi 8 décembre 2007 Statut Membre Dernière intervention 7 décembre 2008 - 8 déc. 2007 à 17:32
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::
pascal.barbier
Messages postés
33
Date d'inscription
samedi 8 décembre 2007
Statut
Membre
Dernière intervention
7 décembre 2008
6
8 déc. 2007 à 11:44
8 déc. 2007 à 11:44
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.
pascal.barbier
Messages postés
33
Date d'inscription
samedi 8 décembre 2007
Statut
Membre
Dernière intervention
7 décembre 2008
6
8 déc. 2007 à 12:36
8 déc. 2007 à 12:36
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
pascal.barbier
Messages postés
33
Date d'inscription
samedi 8 décembre 2007
Statut
Membre
Dernière intervention
7 décembre 2008
6
8 déc. 2007 à 16:53
8 déc. 2007 à 16:53
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);
};
pascal.barbier
Messages postés
33
Date d'inscription
samedi 8 décembre 2007
Statut
Membre
Dernière intervention
7 décembre 2008
6
8 déc. 2007 à 17:32
8 déc. 2007 à 17:32
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"