Académique Documents
Professionnel Documents
Culture Documents
Plan du chapitre
2
Besoin à une telle notion ( fonction amie )
▪ La P.O.O. pure impose l’encapsulation des données. Nous avons vu comment la mettre
en œuvre en C++ : les membres privés (données ou fonctions) ne sont accessibles
qu'aux fonctions membres (publiques ou privées) et seuls les membres publics sont
accessibles "de l'extérieur".
▪ Ce même principe d'encapsulation interdit à une fonction membre d'une classe
d'accéder à des données privées d'une autre classe
• Il est parfois nécessaire d'avoir des fonctions qui ont un accès illimité aux champs d'une classe.
• Comment ? → via des fonctions amies
3
Définition
4
Les différentes situations d'amitié
5
Les différentes situations d'amitiés
1. Fonction indépendante, amie d'une classe,
▪ Exemple class A {
int i;
friend void fct_exemple (A&);
public:
A(){cout << "creation de a";}
};
void fct_exemple (A & b) {
// accès direct à i qui est membre données privées.
cout << b.i << endl; }
int main() {
A y;
fct_exemple(y);
return 0;
}
6
Les différentes situations d'amitiés
1. Fonction indépendante, amie d'une classe,
▪ Remarques
▪ La définition de la fonction amie est différente de la définition d'une fonction membre d'une
classe.
7
Exemple
#include<iostream>
using namespace std;
class X {
int a;
friend void f (X *); Le corps de la fonction est défini plus loin sans faire
}; précéder son nom du nom de la classe (lignes 7 à 9).
Les instructions de cette fonction peuvent cependant
void f (X *p) { atteindront tous les membres de la classe même si ceux-
p->a = 2; ci ne sont pas publics, d'où le nom friend.
cout<<p->a<<endl;
}
int main () {
X *ptr = new X;
f (ptr);
system ("PAUSE");
return 0;
}
8
Les différentes situations d'amitiés
1. Fonction indépendante, amie d'une classe,
▪ Exercice
9
#include<iostream>
using namespace std ;
class point{
int x,y;
public:
point(int abs=0, int ord=0)
{ x= abs;
y=ord; Dans cet exemple, la fonction
} coincide est AMIE de la classe
friend int coincide(point,point);
};
point. C’est une fonction ordinaire
int coincide(point p, point q) qui peut manipuler les membres
{ privés de la classe point.
if ((p.x==q.x)&&(p.y==q.y))return 1 ;
else return 0 ;
}
int main(){
point a(4,0),b(4),c;
if(coincide(a,b)
cout<<"a coincide avec b\n";
else
cout<<"a est différent de b\n";
if(coincide(a,c))
cout<<"a coincide avec c\n";
else
cout<<"a est différent de c\n";
system("PAUSE ") ;
return 0 ; 10
}
Autre exemple
#include <iostream>
using namespace std;
class simple{
int a,b;
public:
friend int somme(simple x);
simple(int,int); //Constructeur
};
simple::simple(int i, int j) {
a=i;
b=j; }
int main(){
simple entier(3,4);
cout<<" La somme de 3 et 4 vaut: "<<endl;
cout<<somme(entier)<<endl;
system("PAUSE");
return 0;
}
11
Les différentes situations d'amitiés
2. Fonction membre d'une classe, amie d'une autre classe
▪ Il s'agit un peu d'un cas particulier de la situation précédente. En fait, il suffit simplement de
préciser, dans la déclaration d'amitié, la classe à laquelle appartient la fonction concernée, à l'aide
de l'opérateur de résolution de portée (::).
▪ Exemple
Supposons que nous ayons à définir deux classes nommées A et B et que nous ayons besoin dans
B d'une fonction membre f, de prototype :
int f(char, A) ;
Si, comme il est probable, f doit pouvoir accéder aux membres privés de A, elle sera déclarée
amie au sein de la classe par :
friend int B::f(char, A) ;
12
Les différentes situations d'amitiés
2. Fonction membre d'une classe, amie d'une autre classe
▪ Exemple (Schema)
class A class B
{ {
// partie privée .....
..... int f (char, A) ;
// partie publique };
friend int B::f (char, A) ; int B::f (char ..., A ...)
..... {
}; // on a accès ici aux membres privés
// de tout objet de type A
}
13
Les différentes situations d'amitiés
2. Fonction membre d'une classe, amie d'une autre classe
▪ Remarques
▪ Pour compiler convenablement les déclarations d'une classe A contenant une déclaration d'amitié telle que :
friend int B::f(char, A) ; le compilateur a besoin de connaître les caractéristiques de B ; cela signifie que la
déclaration de B (mais pas nécessairement la définition de ses fonctions membres) devra avoir été
compilée avant celle de A.
▪ En revanche, pour compiler convenablement la déclaration : int f(char, A) figurant au sein de la classe B, le
compilateur n'a pas besoin de connaître précisément les caractéristiques de A. Il lui suffit de savoir qu'il
s'agit d'une classe. Comme, d'après ce qui vient d’être dit, la déclaration de B n'a pu apparaître avant, on
fournira l'information voulue au compilateur en faisant précéder la déclaration de A de : class A ;
14
#include<iostream>
using namespace std ;
// Déclaration de la classe point
▪ Rien n'empêche qu'une même fonction (qu'elle soit indépendante ou fonction membre) fasse l'objet
de déclarations d'amitié dans différentes classes. Voici un exemple d'une fonction amie de deux
classes A et B :
class A class B
{ {
void f(A..., B...)
// partie privée // partie privée
{
..... .....
// on a accès ici aux membres privés
// partie publique // partie publique
// de n’importe quel objet de type A ou B
friend void f(A, B) ; friend void f(A, B) ;
}
..... .....
}; };
16
Les différentes situations d'amitiés
4. Toutes les fonctions d'une classe amies d'une autre classe
17
Classe Amie #include <iostream>
using namespace std;
class A {
private:
int a;
int b;
public:
A() { a = 2; b=4;}
friend class B; // Classe ami
};
class B {
private:
int b;
public:
void afficherA(A& f) {
//Puisque B est un ami de A, il peut accéder aux membres privés
de A
cout << "La valeur de a dans la classe A = " << f.a<<endl;
}
void afficherA1(A& f1){
cout << "La valeur de b dans la classe A = " << f1.b<<endl;
}
};
int main() {
A a,a1;
B b;
b.afficherA(a);
b.afficherA1(a1); 18
return 0; }
Remarques
▪ Si la classe A est amie de la classe B ⇏ la classe B est amie de la classe A (pas de
symétrie)
▪ Dans le cas de l'amitié décrite dans "fonction indépendante, amie d'une classe", assez souvent
l'amitié est utilisée quand la fonction manipule plus de deux objets à la fois.
▪ Utiliser une fonction membre quand vous pouvez, et une fonction amie quand vous êtes dans
l'obligation de le faire.
19
Exercices
Soit une classe vecteur3d ayant 3 données membres privées, de type entier, les composantes du vecteur
(x,y,z). Elle a un constructeur permettant d’initialiser les données membres.
1 Ecrire une fonction indépendante, coincide, amie de la classe vecteur3d, permettant de savoir si 2
vecteurs ont mêmes composantes. Si v1 et v2 désignent 2 vecteurs de type vecteur3d, écrire le
programme qui permet de tester l’égalité de ces 2 vecteurs.
20
#include<iostream>
using namespace std ;
class vecteur3d{
int x;int y;int z;
public:
vecteur3d(int a=0,int b=0, int c=0);
friend void coincide (vecteur3d p, vecteur3d q);};
vecteur3d::vecteur3d(int a,int b,int c){
x=a;y=b;z=c;
}
void coincide(vecteur3d p, vecteur3d q){
if(p.x==q.x && p.y==q.y && p.z==q.z){
cout<<"Les 2 vecteurs sont egaux"<<endl;
}
else
cout<<"les deux vecteurs ne sont pas egaux"<<endl;}
main(){
vecteur3d v1(3,2,5);
vecteur3d v2(3,4,5);
coincide(v1,v2);
}
21
Exercices
1. Créer 2 classes (dont les membres données sont privés) :
• l’une nommée vecteur, permettant de représenter des vecteurs à 3 composantes de type int ; elle
comportera un constructeur et une fonction membre affiche.
• L’autre nommée matrice, permettant de représenter des matrices carrées de dimension 3x3 ; elle
comportera un constructeur avec un argument (adresse d’un tableau de 3x3 valeurs) qui
initialisera la matrice avec les valeurs correspondantes.
2
2. Réaliser une fonction indépendante prod permettant de fournir le vecteur correspondant au produit
d’une matrice par un vecteur.
3. Réaliser une fonction membre vecteur prod(matrice) faisant le même travail que la fonction
indépendante
4. Ecrire un programme de test.
22
23
#include<iostream>
using namespace std;
class matrice;
class vecteur{
int v[3];
public:
vecteur(int *tab){
for(int i=0;i<3;i++)
v[i] = tab[i];
}
vecteur(){
for(int i=0;i<3;i++)
v[i] = 0;
}
void affiche(){cout<<"("<<v[0]<<","<<v[1]<<","<<v[2]<<")"<<endl;}
24
class matrice{
int m[3][3];
public:
matrice(int tab[3][3]){
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
m[i][j] = tab[i][j]; }
matrice() {
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
m[i][j] = 0; }
void affiche() {
for(int i=0;i<3;i++) {
for(int j=0;j<3;j++)
cout<<m[i][j]<<" ";
cout<<endl;
}
}
//Décalartion d'amitié pour la fonction indépendante
friend vecteur produit(matrice,vecteur);
cout << endl << "Appel avec la fonction membre: " << endl;
res=V.produit(M);
cout << "Le vecteur produit M*V: " << endl;
res.affiche();
return 0;
}
27
#include <iostream>
using namespace std; Toutes les méthodes de Amie sont amies.
class Hote{
friend class Amie;
int i, j; // Donnée privée de la classe Hote.
public:
Hote(){ i=3; j=6;
cout<<" Les données privées de la classe Hote sont\n"<<"i = "<<i<<"
"<<"j="<<j<<endl;
}
void affiche(){cout<<"i="<<i<<" "<<"j="<<j<<endl;}
};
Hote h;
class Amie
{
public:
void print_hote(){
cout<<" La valeur cherchee est \n"<<"i= "<<h.i<<" "<<"j= "<<h.j<<endl;
}
};
int main(){
Amie a;
a.print_hote();
cout<<"\n";
system ("PAUSE");
28
return 0;
}