Professional Documents
Culture Documents
Séquence 2
Séquence 2
I. Introduction
Une fonction membre a accès aux membres publics et privés de la classe. Les données sont masquées, seules
les fonctions membres y ont accès. Le principe d’encapsulation interdit à une fonction membre d’une classe
d’accéder à des données privées d’une autre classe.
Grâce aux fonctions amies, on pourra accéder aux membres privés d’une classe. Une fonction amie d'une classe
est une fonction qui, bien que non-membre de la classe, a accès aux données privées de la classe.
L'amitié est déclarée en utilisant le mot-clé réservé : friend.
Il importe peu de déclarer une fonction amie dans la partie public ou private d'une classe donnée. Dans les deux
cas, la fonction sera vue comme étant une fonction public.
Il existe plusieurs situations d’amitié :
Dr Khalifa SYLLA 1
POO : Langage C++
Séquence 2 : Fonctions amies et surcharges d’opérateurs
Considérons la classe Point(x,y) définie dans les exercices précédents, faire une fonction coincide qui
permet de tester si deux sont égaux. La fonction coïncide est indépendante et amie de la classe point.
Créez un fichier tpfonctionamies.cpp
int main()
{ point a(0,0), b, c ;
if ( coincide (a,b) )
cout<< "A coincide avec B"<<endl;
else
cout<<"A et B sont différents"<<endl;
return 0:
};
Dr Khalifa SYLLA 2
POO : Langage C++
Séquence 2 : Fonctions amies et surcharges d’opérateurs
IV. Toutes les fonctions d’une classe B sont amies d’une autre classe A
Dans ce cas, plutôt que d’utiliser autant de déclarations d’amitié que de fonctions membre, on utilise (dans la
déclaration de la classe A) la déclaration (globale) suivante : friend class B ; Pour compiler la déclaration de
A, on précisera simplement que B est une classe par : class B ; Quant à la déclaration de la classe B, elle
nécessitera généralement (dès qu’une de ses fonctions membre possédera un argument ou une valeur de retour
de type A) la déclaration de la classe A.
Remarque
L’amitié n’est ni symétrique ni transitive
- Si la classe A est amie de la classe B n’implique pas que la classe B est amie de la classe A (pas de
symétrie),
- Si la classe A est amie de la classe B ET si la classe B est amie de la classe C n’implique pas que la classe A
est amie de la classe C (pas de transitivité).
- Souvent l'amitié est utilisée quand la fonction manipule plus de deux objets à la fois. - Sinon, on utilise une
fonction membre d'une classe.
- Utiliser une fonction membre quand vous pouvez, et une fonction amie quand vous êtes dans l'obligation de
le faire.
Dr Khalifa SYLLA 3
POO : Langage C++
Séquence 2 : Fonctions amies et surcharges d’opérateurs
Exercice 1
Soit la classe point suivante : class point { int x, y ; public : point (int abs=0, int ord=0) { x = abs ; y = ord ; } }
; Écrire une fonction indépendante affiche, amie de la classe point, permettant d’afficher les coordonnées d’un
point. On fournira séparément un fichier source contenant la nouvelle déclaration (définition) de point et un
fichier source contenant la définition de la fonction affiche. Écrire un petit programme (main) qui crée un point
de classe automatique et un point de classe dynamique et qui en affiche les coordonnées.
Exercice 2
Créer deux classes (dont les membres donnés sont privés) :
L’une, nommée vect, permettant de représenter des vecteurs à 3 composantes de type double; elle comportera
un constructeur et une fonction membre d’affichage ;
L’autre, nommée matrice, permettant de représenter des matrices carrées de dimension 3 x 3 ; elle
comportera un constructeur avec un argument (adresse d’un tableau de 3 x 3 valeurs) qui initialisera la
matrice avec les valeurs correspondantes. Réaliser une fonction indépendante prod permettant de fournir le
vecteur correspondant au produit d’une matrice par un vecteur. Écrire un petit programme de test. On
fournira séparément les deux déclarations de chacune des classes, leurs deux définitions, la définition de
prod et le programme de test
Surcharges d’opérateurs
Considérons une classe Complexe chargée d’implémenter la gestion des nombres complexes dans un
programme. On va certainement être amené à définir les opérations courantes sur ces nombres. Par exemple,
l’addition entre deux nombres complexes pourrait se définir comme une fonction ayant comme prototype :
Complexe add(const Complexe &) ; Pour appeler cette fonction dans un programme on utilisera la syntaxe
suivante :
Complexe c1(1, 1), c2(2, 2);
Complexe c3 = c1.add(c2) ;
Cette solution marche bien, mais on est habitué à une écriture qui nous semble plus naturelle : On aurait envie
d’écrire : Complexe c3 = c1 + c2;
L’opérateur ‘+’ existe bien en C++, mais il n’existe que pour des types prédéfinis, de base, tels que int, float,
double, etc. Pour que nous puissions l’utiliser dans le cadre des nombres complexes que nous avons définis, il
faudrait que nous puissions le redéfinir dans ce contexte.
Le langage C++ autorise le programmeur à étendre la signification d’opérateurs.
On appelle ce mécanisme la surcharge ou surdéfinition d’opérateurs.
Dr Khalifa SYLLA 4
POO : Langage C++
Séquence 2 : Fonctions amies et surcharges d’opérateurs
La plupart des opérateurs peuvent être redéfinis ou surchargés, seuls quelques-uns échappent à cette règle. Les
opérateurs suivants ne peuvent pas être redéfinis :
o :: (opérateur de résolution de portée)
o . (opérateur point, pour accéder aux champs d’un objet)
o sizeof
o ?: (opérateur ternaire)
A Op B
se traduisant par :
A.operatorOp(B)
Avec cette syntaxe, le premier opérande est toujours l'objet auquel cette fonction s'applique. Les paramètres de
la fonction opérateur sont alors le deuxième opérande et les suivants.
Les opérateurs définis en interne devront souvent renvoyer l'objet sur lequel ils travaillent Cela est faisable grâce
au pointeur this.
Dr Khalifa SYLLA 5
POO : Langage C++
Séquence 2 : Fonctions amies et surcharges d’opérateurs
Exemple
class complexe
{
double m_x, m_y; // Les parties réelles et imaginaires.
public:
// Constructeurs et opérateur de copie :
complexe(double x=0, double y=0);
complexe(const complexe &);
complexe &operator=(const complexe &);
complexe::complexe(double x, double y)
{
m_x = x;
m_y = y;
return ;
}
Dr Khalifa SYLLA 6
POO : Langage C++
Séquence 2 : Fonctions amies et surcharges d’opérateurs
{
double norm = c.m_x*c.m_x + c.m_y*c.m_y;
double temp = (m_x*c.m_x + m_y*c.m_y) / norm;
m_y = (-m_x*c.m_y + m_y*c.m_x) / norm;
m_x = temp;
return *this;
}
Une deuxième possibilité nous est offerte par le langage pour surcharger les opérateurs. La définition de
l'opérateur ne se fait plus dans la classe qui l'utilise, mais en dehors de celle-ci, par surcharge d'un opérateur de
l'espace de nommage global. Il s'agit donc d'opérateurs externes cette fois.
La surcharge des opérateurs externes se fait donc exactement comme on surcharge les fonctions normales. Dans
ce cas, tous les opérandes de l'opérateur devront être passés en paramètres : il n'y aura pas de paramètre implicite
(le pointeur this n'est pas passé en paramètre).
type operatorOp(opérandes)
où opérandes est la liste complète des opérandes.
Exemple
class complexe
{
friend complexe operator+(const complexe &, const complexe &);
friend complexe operator-(const complexe &, const complexe &);
friend complexe operator*(const complexe &, const complexe &);
friend complexe operator/(const complexe &, const complexe &);
Dr Khalifa SYLLA 7
POO : Langage C++
Séquence 2 : Fonctions amies et surcharges d’opérateurs
Dr Khalifa SYLLA 8