Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare une entreprise Scribd logo

1

Chapitre VI
Les fonctions et classes
amies
• L'encapsulation des données restreint l'accès aux membres données d'une classe aux
fonctions membres de cette classe. Mais parfois, il est utile d'avoir des fonctions non
membres d'une classe qui ont accès aux données privées de cette dernière.
• C++ introduit alors la notion "d'amitié" entre fonctions et classes, ce qui permet de
définir des fonctions, appelées fonctions amies d'une classe, qui peuvent accéder à
tous les membres de cette classe.
• C++ permet aussi de déclarer une classe amie d'une autre classe.
• Une classe ou une fonction amie d'une classe est déclarée dans la classe avec le mot
clé friend.
VI.1 Les fonctions amies
Pour une fonction amie d'une classe, on distingue trois situations :
♦ La fonction est indépendante (n'est membre d'aucune classe)
♦ La fonction est membre d'une autre classe
♦ La fonction est une fonction amie d'une autre classe

2

Les fonctions et classes amies 52
Fonction indépendante amie d'une classe
• Pour qu'une fonction fct de prototype
type_r fct(liste_arguments);
soit une fonction amie d'une classe T, il faut la déclarer dans la classe T avec le mot-
clé friend, comme suit :
class T{
...
public:
...
friend type_r fct(liste_arguments);
...
}
• Notons que pour justifier la déclaration d'amitié d'une fonction donnée à une classe, il
faut que cette fonction possède un argument ou une valeur de retour de type de la
classe.
Exemple 6.1
Pour la classe point (manipulation des points du plan), on souhaite définir une fonction
coincide() qui permet de comparer deux points.
: (EXP06_01.CPP)
Pour ce, on peut définir la fonction soit comme fonction membre (voir Exemple 4.3), soit
comme fonction amie de la classe point.
//---------- Classe point
class point{
int x;
int y;
public:
point(int abs = 0, int ord = 0){
x = abs; y = ord;
}
friend bool coincide(point,point);
void point::affiche(){
cout << "(" << x << "," << y << ")" << endl;
}
};
//----------- TEST
int main()
{
point a,c;
point b(5,6);
cout << ( coincide(a,c) ? "-> a = c" : "-> a <> c" ) << endl;
cout << ( coincide(a,b) ? "-> a = b" : "-> a <> b" ) << endl;
return 0;
}
//-------- définition de la fonction amie coincide
bool coincide(point u, point v){
return ( (u.x == v.x) && (u.y == v.y) );
}

3

Les fonctions et classes amies 53
Notez qu'il est inutile de déclarer la fonction coincide() à l'extérieur de la classe, parce
qu'elle l'est déjà à l'intérieur de la classe.
Fonction membre d'une classe amie d'une autre classe
• Pour déclarer une fonction fct membre d'une classe A, comme fonction amie d'une
classe T, il faut que la fonction soit déclarée avec le nom de sa classe et l'opérateur de
résolution de portée, comme suit :
class T{
… …
public:
… …
friend type_r A::fct(liste_arguments);
… …
}
• Pour compiler convenablement la classe T, il faut que le compilateur accède à la
déclaration complète de A. Pour ce, il faut que la déclaration de A précède celle de T.
D'autre part, puisque fct a un argument ou une valeur de retour de type T, il faut
donc signaler au compilateur que T est une classe, avant la déclaration de la classe A.
Ainsi, si les deux déclarations se trouvent dans le même fichier, on doit avoir le
schéma suivant:
class T; // signale au compilateur que T est une classe
//------------------- déclaration de A
class A{……};
//------------------- déclaration de T
class T{……};
//-- définition de la fonction membre de A amie de T
...
Exemple 6.2
L'exemple suivant montre l'utilisation d'une fonction membre d'une classe et amie d'une
autre classe en programmation modulaire.
: (EXP06_02)
On considère une classe nommée matrice qui permet de manipuler les matrice 2x2, et
une classe nommé vecteur pour manipuler les vecteurs à 2 composantes. Puis, on
souhaite définir une fonction nommée colonne() qui permet d'extraire d'une matrice
ses vecteurs colonnes.
L'exemple offre une solution, en définissant la fonction colonne comme membre de la
classe matrice et amie de la classe vecteur.
►Interface de la classe matrice (MATRICE1.H)
#ifndef _MATRICE
#define _MATRICE
class vecteur; // nécessaire pour la compilation
class matrice{

4

Les fonctions et classes amies 54
double mat[2][2];
public:
matrice (double [2][2]);
vecteur colonne(int);
void affiche();
};
#endif
►Interface de la classe vecteur (VECTEUR1.H)
#ifndef _VECTEUR
#define _VECTEUR
#include "matrice1.h" // la déclaration complète de 'matrice'
class vecteur{
double vect[2];
public:
vecteur (double = 0, double = 0);
friend vecteur matrice::colonne(int);
void affiche();
};
#endif
►Corps de la classe matrice (MATRICE1.CPP)
#include "matrice1.h"
#include "vecteur1.h" // nécessaire pour la fonction colonne(...)
#include <iostream>
using namespace std;
matrice::matrice (double t[2][2]){
int i,j;
for(i = 0; i < 2; i++)
for(j = 0; j < 2; j++)
mat[i][j] = t[i][j];
}
void matrice::affiche(){
cout << mat[0][0] << "t" << mat[0][1] << endl;
cout << mat[1][0] << "t" << mat[1][1] << endl;
}
/*********************************************************************
Fonction : colonne() amie de 'vecteur'
Retourne colonne k si k = 1 ou 2, sinon elle retourne le vecteur nul
*********************************************************************/
vecteur matrice::colonne(int k){
vecteur v;
if((k == 1) || (k == 2))
for(int i = 0; i < 2; i++)
v.vect[i] = mat[i][k-1];
return v;
}
►Corps de la classe vecteur (VECTEUR1.CPP)
#include "vecteur1.h"
#include <iostream>
using namespace std;
vecteur::vecteur(double v1, double v2){
vect[0]= v1;

5

Les fonctions et classes amies 55
vect[1]= v2;
}
void vecteur::affiche(){
for(int i=0; i<2; i++)
cout << vect[i] << " ";
cout << endl;
}
►Programme test (EXP06_02.CPP)
#include "matrice1.h"
#include "vecteur1.h"
#include <iostream>
using namespace std;
int main(){
double tb[2][2] = {{1,2},{3,4}};
matrice a = tb;
a.affiche();
vecteur v1 = a.colonne(1);
cout << "colonne 1 : " ; v1.affiche();
vecteur v2 = a.colonne(2);
cout << "colonne 2 : " ; v2.affiche();
return 0;
}
Fonction amie de plusieurs classes
• Pour qu'une fonction soit amie des classes A et B, il suffit de déclarer cette amitié pour
les deux classes concernées. Cependant, il faut noter que pour une compilation séparée
de A il faut signaler au compilateur que B est une classe et vice-versa.
Exemple 6.3
On reprend les mêmes classes décrites dans l'exemple 6.2, et on définit cette fois ci le
produit d'une matrice par un vecteur.
: (EXP06_03)
La fonction produit() sera déclarée comme amie des deux classes et sera compilée
séparément.
►Interface de la classe matrice (MATRICE2.H)
#ifndef _MATRICE
#define _MATRICE
class vecteur; // nécessaire pour la compilation
class matrice{
double mat[2][2];
public:
matrice (double [2][2]);
friend vecteur produit(matrice,vecteur);
void affiche();
};
#endif
►Interface de la classe vecteur (VECTEUR2.H)
#ifndef _VECTEUR
#define _VECTEUR

6

Les fonctions et classes amies 56
class matrice; // nécessaire pour la compilation
class vecteur{
double vect[2];
public:
vecteur (double = 0, double = 0);
friend vecteur produit(matrice,vecteur);
void affiche();
};
#endif
►Corps de la classe matrice (MATRICE2.CPP)
#include "matrice2.h"
#include <iostream>
matrice::matrice (double t[2][2]){
int i,j;
for(i = 0; i < 2; i++)
for(j = 0; j < 2; j++)
mat[i][j] = t[i][j];
}
void matrice::affiche(){
std::cout << mat[0][0] << "t" << mat[0][1] << std::endl;
std::cout << mat[1][0] << "t" << mat[1][1] << std::endl;
}
►Corps de la classe vecteur (VECTEUR2.CPP)
#include "vecteur2.h"
#include <iostream>
vecteur::vecteur(double v1, double v2){
vect[0]= v1;
vect[1]= v2;
}
void vecteur::affiche(){
std::cout << "[ " << vect[0] << ", "
<< vect[1] << " ]" << std::endl;
}
►Implémentation de la fonction produit (PRODUIT.CPP)
#include "matrice2.h"
#include "vecteur2.h"
vecteur produit(matrice m, vecteur u){
int i, j;
double som;
vecteur res;
for(i=0; i<2; i++){
for(j=0,som=0; j<2; j++)
som += m.mat[i][j] * u.vect[j];
res.vect[i] = som;
}
return res;
}
►Programme test (EXP06_03.CPP)
#include "matrice2.h"
#include "vecteur2.h"

7

Les fonctions et classes amies 57
#include <iostream>
using namespace std;
int main()
{
double tb[2][2] = {{1,2},{3,4}};
matrice a = tb;
a.affiche();
vecteur u(4,5);
u.affiche();
vecteur v;
v = produit(a,u);
cout << "produit = " ; v.affiche();
return 0;
}
VI.2 Classes amies
• Pour rendre toutes les fonctions membres d'une classe B, amies d'une classe A, on
déclare la classe B comme amie de la classe A à l'intérieure de la déclaration de A avec
le mot clé friend, comme suit:
class A{
… …
public:
… …
friend class B;
… …
}
• Cependant, il faut noter que l'amitié n'est pas transitive, autrement dit, si une classe B
est amie d'une classe A et si une classe C est amie de B, la classe C n'est pas
automatiquement amie de A.

8

Les fonctions et classes amies 58

Contenu connexe

Ch06

  • 1. Chapitre VI Les fonctions et classes amies • L'encapsulation des données restreint l'accès aux membres données d'une classe aux fonctions membres de cette classe. Mais parfois, il est utile d'avoir des fonctions non membres d'une classe qui ont accès aux données privées de cette dernière. • C++ introduit alors la notion "d'amitié" entre fonctions et classes, ce qui permet de définir des fonctions, appelées fonctions amies d'une classe, qui peuvent accéder à tous les membres de cette classe. • C++ permet aussi de déclarer une classe amie d'une autre classe. • Une classe ou une fonction amie d'une classe est déclarée dans la classe avec le mot clé friend. VI.1 Les fonctions amies Pour une fonction amie d'une classe, on distingue trois situations : ♦ La fonction est indépendante (n'est membre d'aucune classe) ♦ La fonction est membre d'une autre classe ♦ La fonction est une fonction amie d'une autre classe
  • 2. Les fonctions et classes amies 52 Fonction indépendante amie d'une classe • Pour qu'une fonction fct de prototype type_r fct(liste_arguments); soit une fonction amie d'une classe T, il faut la déclarer dans la classe T avec le mot- clé friend, comme suit : class T{ ... public: ... friend type_r fct(liste_arguments); ... } • Notons que pour justifier la déclaration d'amitié d'une fonction donnée à une classe, il faut que cette fonction possède un argument ou une valeur de retour de type de la classe. Exemple 6.1 Pour la classe point (manipulation des points du plan), on souhaite définir une fonction coincide() qui permet de comparer deux points. : (EXP06_01.CPP) Pour ce, on peut définir la fonction soit comme fonction membre (voir Exemple 4.3), soit comme fonction amie de la classe point. //---------- Classe point class point{ int x; int y; public: point(int abs = 0, int ord = 0){ x = abs; y = ord; } friend bool coincide(point,point); void point::affiche(){ cout << "(" << x << "," << y << ")" << endl; } }; //----------- TEST int main() { point a,c; point b(5,6); cout << ( coincide(a,c) ? "-> a = c" : "-> a <> c" ) << endl; cout << ( coincide(a,b) ? "-> a = b" : "-> a <> b" ) << endl; return 0; } //-------- définition de la fonction amie coincide bool coincide(point u, point v){ return ( (u.x == v.x) && (u.y == v.y) ); }
  • 3. Les fonctions et classes amies 53 Notez qu'il est inutile de déclarer la fonction coincide() à l'extérieur de la classe, parce qu'elle l'est déjà à l'intérieur de la classe. Fonction membre d'une classe amie d'une autre classe • Pour déclarer une fonction fct membre d'une classe A, comme fonction amie d'une classe T, il faut que la fonction soit déclarée avec le nom de sa classe et l'opérateur de résolution de portée, comme suit : class T{ … … public: … … friend type_r A::fct(liste_arguments); … … } • Pour compiler convenablement la classe T, il faut que le compilateur accède à la déclaration complète de A. Pour ce, il faut que la déclaration de A précède celle de T. D'autre part, puisque fct a un argument ou une valeur de retour de type T, il faut donc signaler au compilateur que T est une classe, avant la déclaration de la classe A. Ainsi, si les deux déclarations se trouvent dans le même fichier, on doit avoir le schéma suivant: class T; // signale au compilateur que T est une classe //------------------- déclaration de A class A{……}; //------------------- déclaration de T class T{……}; //-- définition de la fonction membre de A amie de T ... Exemple 6.2 L'exemple suivant montre l'utilisation d'une fonction membre d'une classe et amie d'une autre classe en programmation modulaire. : (EXP06_02) On considère une classe nommée matrice qui permet de manipuler les matrice 2x2, et une classe nommé vecteur pour manipuler les vecteurs à 2 composantes. Puis, on souhaite définir une fonction nommée colonne() qui permet d'extraire d'une matrice ses vecteurs colonnes. L'exemple offre une solution, en définissant la fonction colonne comme membre de la classe matrice et amie de la classe vecteur. ►Interface de la classe matrice (MATRICE1.H) #ifndef _MATRICE #define _MATRICE class vecteur; // nécessaire pour la compilation class matrice{
  • 4. Les fonctions et classes amies 54 double mat[2][2]; public: matrice (double [2][2]); vecteur colonne(int); void affiche(); }; #endif ►Interface de la classe vecteur (VECTEUR1.H) #ifndef _VECTEUR #define _VECTEUR #include "matrice1.h" // la déclaration complète de 'matrice' class vecteur{ double vect[2]; public: vecteur (double = 0, double = 0); friend vecteur matrice::colonne(int); void affiche(); }; #endif ►Corps de la classe matrice (MATRICE1.CPP) #include "matrice1.h" #include "vecteur1.h" // nécessaire pour la fonction colonne(...) #include <iostream> using namespace std; matrice::matrice (double t[2][2]){ int i,j; for(i = 0; i < 2; i++) for(j = 0; j < 2; j++) mat[i][j] = t[i][j]; } void matrice::affiche(){ cout << mat[0][0] << "t" << mat[0][1] << endl; cout << mat[1][0] << "t" << mat[1][1] << endl; } /********************************************************************* Fonction : colonne() amie de 'vecteur' Retourne colonne k si k = 1 ou 2, sinon elle retourne le vecteur nul *********************************************************************/ vecteur matrice::colonne(int k){ vecteur v; if((k == 1) || (k == 2)) for(int i = 0; i < 2; i++) v.vect[i] = mat[i][k-1]; return v; } ►Corps de la classe vecteur (VECTEUR1.CPP) #include "vecteur1.h" #include <iostream> using namespace std; vecteur::vecteur(double v1, double v2){ vect[0]= v1;
  • 5. Les fonctions et classes amies 55 vect[1]= v2; } void vecteur::affiche(){ for(int i=0; i<2; i++) cout << vect[i] << " "; cout << endl; } ►Programme test (EXP06_02.CPP) #include "matrice1.h" #include "vecteur1.h" #include <iostream> using namespace std; int main(){ double tb[2][2] = {{1,2},{3,4}}; matrice a = tb; a.affiche(); vecteur v1 = a.colonne(1); cout << "colonne 1 : " ; v1.affiche(); vecteur v2 = a.colonne(2); cout << "colonne 2 : " ; v2.affiche(); return 0; } Fonction amie de plusieurs classes • Pour qu'une fonction soit amie des classes A et B, il suffit de déclarer cette amitié pour les deux classes concernées. Cependant, il faut noter que pour une compilation séparée de A il faut signaler au compilateur que B est une classe et vice-versa. Exemple 6.3 On reprend les mêmes classes décrites dans l'exemple 6.2, et on définit cette fois ci le produit d'une matrice par un vecteur. : (EXP06_03) La fonction produit() sera déclarée comme amie des deux classes et sera compilée séparément. ►Interface de la classe matrice (MATRICE2.H) #ifndef _MATRICE #define _MATRICE class vecteur; // nécessaire pour la compilation class matrice{ double mat[2][2]; public: matrice (double [2][2]); friend vecteur produit(matrice,vecteur); void affiche(); }; #endif ►Interface de la classe vecteur (VECTEUR2.H) #ifndef _VECTEUR #define _VECTEUR
  • 6. Les fonctions et classes amies 56 class matrice; // nécessaire pour la compilation class vecteur{ double vect[2]; public: vecteur (double = 0, double = 0); friend vecteur produit(matrice,vecteur); void affiche(); }; #endif ►Corps de la classe matrice (MATRICE2.CPP) #include "matrice2.h" #include <iostream> matrice::matrice (double t[2][2]){ int i,j; for(i = 0; i < 2; i++) for(j = 0; j < 2; j++) mat[i][j] = t[i][j]; } void matrice::affiche(){ std::cout << mat[0][0] << "t" << mat[0][1] << std::endl; std::cout << mat[1][0] << "t" << mat[1][1] << std::endl; } ►Corps de la classe vecteur (VECTEUR2.CPP) #include "vecteur2.h" #include <iostream> vecteur::vecteur(double v1, double v2){ vect[0]= v1; vect[1]= v2; } void vecteur::affiche(){ std::cout << "[ " << vect[0] << ", " << vect[1] << " ]" << std::endl; } ►Implémentation de la fonction produit (PRODUIT.CPP) #include "matrice2.h" #include "vecteur2.h" vecteur produit(matrice m, vecteur u){ int i, j; double som; vecteur res; for(i=0; i<2; i++){ for(j=0,som=0; j<2; j++) som += m.mat[i][j] * u.vect[j]; res.vect[i] = som; } return res; } ►Programme test (EXP06_03.CPP) #include "matrice2.h" #include "vecteur2.h"
  • 7. Les fonctions et classes amies 57 #include <iostream> using namespace std; int main() { double tb[2][2] = {{1,2},{3,4}}; matrice a = tb; a.affiche(); vecteur u(4,5); u.affiche(); vecteur v; v = produit(a,u); cout << "produit = " ; v.affiche(); return 0; } VI.2 Classes amies • Pour rendre toutes les fonctions membres d'une classe B, amies d'une classe A, on déclare la classe B comme amie de la classe A à l'intérieure de la déclaration de A avec le mot clé friend, comme suit: class A{ … … public: … … friend class B; … … } • Cependant, il faut noter que l'amitié n'est pas transitive, autrement dit, si une classe B est amie d'une classe A et si une classe C est amie de B, la classe C n'est pas automatiquement amie de A.
  • 8. Les fonctions et classes amies 58