Vous êtes sur la page 1sur 29

Le langage C++ et la programmation orientée

objets - séances 8 et 9 -

Prof. Karim Rhofir

ENSA Khouribga

Décembre 2021
Fonctions et classes amies
Fonctions amies
Il existe un autre moyen pour une fonction quelconque
d’accéder aux membres privés d’une classe. Il s’agit d’une
fonction amie (friend).
Celle-ci se déclare dans le corps de la classe, précédée du mot
clé friend.
Elle accède aux attributs privés sans l’utilisation des getters
ou des setters.

class MaClasse { . . .
// fonction amie et non une methode
friend type - ret Fonct ( ... );
};
/* ici on definie la fonction fonct ()
sans operateur de portee */

Prof. Karim Rhofir C++ & POO


Fonctions et classes amies
Classes amies
Comme pour une fonction quelconque une classe peut accéder
aux membres privés d’une autre classe. Il s’agit de la déclarer
comme classe amie (friend).
Celle-ci se déclare dans le corps de la classe, précédée du mot
clé friend.
Ses méthodes accèdent aux attributs privés sans l’utilisation
des getters ou des setters.

class TaClasse {...};

class MaClasse { . . .
// declaration de la classe amie
friend class TaClasse ;
};

Prof. Karim Rhofir C++ & POO


Fonctions et classes amies

Fonctions et Classes amies en résumé


Les amis d’une classe sont des classes ou des fonctions
Les amis d’une classe peuvent accéder à toutes les méthodes
et attributs de la classe quel que soit le niveau de protection,
Les amis d’une classe sont déclarées à l’intérieur de la classe,
Violation parfois utile, mais très souvent déconseillée, du
principe d’encapsulation.

Prof. Karim Rhofir C++ & POO


Surcharge d’opérateurs
Motivations
Quand on crée une classe, c’est comme si on crée un nouveau
’type’, l’idée de la surcharge des opérateurs, c’est de pouvoir
utiliser les opérateurs du C++ pour le ’type’ qu’on a crée. Comme
par exemple :
class Matrice
{ public :
void afficher ();
Matrice Additionner ( Matrice &);
Matrice ( int , int ); // Constructeur
~ Matrice ( ); // destructeur
private :
int ligne ;
int colonne ;
int ** tab ;
};

Prof. Karim Rhofir C++ & POO


Surcharge d’opérateurs
Motivations (suite)
Pour additionner 2 matrices on utilisera la méthode Additionner(
Matrice ), mais on aimerait utiliser l’operateur + pour les
additionner comme les types de bases (int, float, etc. . .)
int main (){
Matrice M (2 ,2);
M . remplit ();
Matrice N (2 ,2);
N . remplit ();
/* on aimerait utiliser M + N
pour additionner les 2 matrices */
( M + N ). afficher ();
/* on aimerait utiliser cout < < M ;
pour afficher une matrice au
lieu de la methode affiche () */
}

Prof. Karim Rhofir C++ & POO


Surcharge d’opérateurs

Motivations (suite)
En C++, les opérateurs définis pour les types de base sont
traités par le compilateur comme des fonctions, ce qui permet
donc, avec la technique de la surcharge, d’utiliser la plus part
d’entre eux avec les types classe.
Les opérateurs surchargeables sont :

Les opérateurs qui ne peuvent être surchargés :

Prof. Karim Rhofir C++ & POO


Surcharge d’opérateurs

Technique de surcharge d’opérateurs


Pour surcharger un opérateur X, on définit la fonction
opérateur X (par exemple opérateur+() pour l’addition).
L’implémentation de la surcharge d’un opérateur peut se faire
soit comme une fonction classique globale (amie d’une classe),
soit comme une méthode de classe.
La surcharge d’un opérateur est appelée implicitement par le
compilateur chaque fois que l’opérateur est rencontré dans le
code, mais elle peut être aussi appelée explicitement avec la
notation fonctionnelle.

Prof. Karim Rhofir C++ & POO


Surcharge d’opérateurs
Syntaxe de déclaration
Syntaxe générale :
type_de_retour operator X(liste arg) ;
X étant l’opérateur à surcharger doit obligatoirement être un
opérateur déjà défini pour les types de base, comme : +, -,=,
«, », . . .

Exemple :
class Point{ . . .
/*déclaration de la surcharge de l’opérateur + en tant que
méthode de classe*/
Point operator +(Point ) ;
/*déclaration de la surcharge de l’opérateur - en tant que
fonction amie */
friend Point operator -(Point, Point) ;
};
Prof. Karim Rhofir C++ & POO
Surcharge d’opérateurs

Surcharge d’opérateurs
La surcharge d’opérateurs ne peut pas avoir des arguments par
défaut et doit conserver la pluralité (unaire, binaire) de
l’opérateur initial :
Opérateurs unaires :+, -, ++, –, , *, new, delete, ( ),. . .
Opérateurs binaires : *, +, -, «, »,<, <=, >, >=,[],. . .
Il y a des opérateurs qu’on ne peut pas surcharger : .,
sizeof,. . .
Les opérateurs =,[], (), ->, new et delete doivent être
redéfinis comme méthode de classe (et non comme fonctions
amies).
L’ordre de priorité des opérateur est conservé.
Il n’est pas possible de créer de nouveaux opérateurs.

Prof. Karim Rhofir C++ & POO


Surcharge d’opérateurs

Surcharge d’opérateurs en tant que fonction amie


Les arguments de la fonction correspondent aux opérandes de
l’opérateur
Au moins un des autres opérandes est de type classe.

Exemple :
class Point{
/*déclaration de la surcharge de l’opérateur + en tant que
fonction amie */
friend Point operator +(Point, Point) ; } ;
déclarer l’amitié dans la classe Point
définir la fonction globale amie à lextérieur de la classe

Prof. Karim Rhofir C++ & POO


Surcharge d’opérateurs

Exemple :

Prof. Karim Rhofir C++ & POO


Surcharge d’opérateurs

Surcharge d’opérateurs en tant que méthode de classe


La première opérande de l’opérateur transmise implicitement
doit être l’objet auquel on applique la méthode,
Si l’opérateur est binaire, pas de contrainte de type imposé sur
l’argument explicite.

Exemple :
class Point{
/*déclaration du protoype de la surcharge de l’opérateur +
en tant que méthode */
Point operator+( Point) ; } ;
Point Point : :operator+(Point P). . .

Prof. Karim Rhofir C++ & POO


Surcharge d’opérateurs

Exemple :

Prof. Karim Rhofir C++ & POO


Surcharge d’opérateurs
Surcharge de l’opérateur d’affectation (=)
On a vu précédemment les problèmes de l’affectation entre objets si
on utilisait l’affectation par défaut. Pour remédier à ce problème
il faut surcharger l’opérateur d’affectation pour le type objet.
Pour cela, il faut respecter les contraintes suivantes :
La surcharge de l’opérateur d’affectation doit être déclaré
comme une méthode de classe en C++.
Pouvoir affecter un objet à lui même : A=A ;
Pouvoir faire une affectation multiple : A=B=C=. . . ;

Remarque :
Il y a une différences entre l’implémentation du constructeur par
recopie et celle de la surcharge de l’opérateur = :
affectation d’un objet à lui-même possible,
avant l’affectation : les 2 objets existent, (déjà construits).

Prof. Karim Rhofir C++ & POO


Surcharge d’opérateurs
Surcharge de l’opérateur d’affectation (=) (suite)
Surchargeons l’opérateur= pour la classe Matrice, vue
précédemment. La méthode est identique pour toute surcharge de
l’opérateur= pour n’importe quelle classe :
class Matrice { ...
// on declare le prototype dans la classe
Matrice & operator =( const Matrice &);
/* le type de retour est de type objet pour
pouvoir effectuer l ’ affectation multiple
A = B = C ; en ecriture fonctionnelle ca donne :
( A . operator ( B )). operator =( C );
donc A . operator =( B ) doit etre une matrice */
....
};

Prof. Karim Rhofir C++ & POO


Surcharge d’opérateurs

Surcharge de l’opérateur d’affectation (=) (suite)


la définition se fera en dehors de la classe en suivant les étapes
suivantes :
On doit libérer la mémoire de l’objet courant,
On doit allouer un nouvel emplacement mémoire de la même
taille que la deuxième opérande (ici ça sera l’objet B),
On copie les valeurs de B dans l’objet courant,
on retourne l’objet courant par *this.

Prof. Karim Rhofir C++ & POO


Surcharge d’opérateurs
Surcharge de l’opérateur d’affectation (=) (suite)

Matrice & Matrice :: operator =( const Matrice & B ){


/* On commence par tester si l objet courant
est different de B , ce teste se fera par les
pointeurs si on n a pas surcharge operator !=
car si on veut affecter l objet courant
a lui - meme il ne faut pas le detruire */
if ( this != & B ){
// liberation memoire
for ( int i =0; i < ligne ; i ++)
delete [] tab [ i ];
delete [] tab ;
// nouvelle allocation
tab = new float [ B . ligne ];
for ( int i =0; i < B . ligne ; i ++)
tab [ i ]= new float [ B . colonne ];

Prof. Karim Rhofir C++ & POO


Surcharge d’opérateurs
Surcharge de l’opérateur d’affectation (=) (suite)

// copie des valeurs de B dans l objet courant


ligne = B . ligne ;
colonne = B . colonne ;
// on copie les coefficients de la matrice B
for ( int i =0; i < B . ligne ; i ++)
for ( int j =0; j < B . colonne ; i ++)
tab [ i ][ j ]= B . tab [ i ][ j ];

return * this ;
}
else return * this ;
}

Prof. Karim Rhofir C++ & POO


Surcharge d’opérateurs
Forme canonique d’une classe
Avec la surcharge de l’affectation, une classe doit avoir la forme
canonique suivante, surtout si elle possède des attributs pointeurs :
class MaClasse {
public :
// constructeur
MaClasse (...) ;
// constructeur de recopie
MaClasse ( const MaClasse &) ;
// destructeur
~ MaClasse () ;
// operateur d affectation
MaClasse & operator = ( const MaClasse &) ;
} ;

Prof. Karim Rhofir C++ & POO


Surcharge d’opérateurs

Surcharge de l’opérateur de conversion :(cast)


Si un opérateur de conversion est défini, on peut affecter
l’objet dans une variable du type correspondant
Doit être déclaré comme méthode de classe en C++,
Pas de type de retour spécifié :type = nom de l’opérateur
operator type-conversion() ;
Pas de paramètres,
Retour de l’objet converti.

Prof. Karim Rhofir C++ & POO


Surcharge d’opérateurs
Surcharge de l’opérateur de conversion :(cast)(suite)
On va prendre pour exemple la classe Point, et on va définir
l’opérateur de conversion du type Point vers le type double par
exemple.
class Point {...
public :
// prototype operateur de conversion
operator double (); // operateur unaire
...
} ;
// l implementation
Point :: operator double (){
/* on peut definir notre facon de faire
la conversion pour obtenir ici un double */
return sqrt ( x * x + y * y ) ;
}

Prof. Karim Rhofir C++ & POO


Surcharge d’opérateurs
Surcharge de l’opérateur de conversion :(cast)(suite)

// l utilisation
int main (){
Point pt (10 ,3) ;
double f ;
f = ( double ) pt ;
// ou double ( pt );( ecriture fonctionnelle )

// une autre utilisation


f = f + pt ; // OK
/* ici meme si on n a pas surcharge
l operateur + pour additionner un double
avec un Point , le compilateur va effectuer
une conversion implicite du type Point
vers le type double */
}

Prof. Karim Rhofir C++ & POO


Surcharge d’opérateurs
Remarque sur les conversions :
Si la classe ne comporte qu’un seul attribut du type de base
MaClasse U(valeur) ; et MaClasse U = valeur ; seront
équivalentes. Dans la deuxième écriture, il y aura une conversion
implicite du type de valeur vers MaClasse.
class MaClasse {
float z ; // un seul attribut de type float
public :
MaClasse ( float x =0.0){ z = x ;}
......
};
// La declaration suivante est correcte
MaClasse U = 1.2;
// conversion implicite float - > MaClasse

Prof. Karim Rhofir C++ & POO


Surcharge d’opérateurs

Surcharge des opérateurs < < et > >


On voudrait surcharge les opérateurs « et » pour les types objets,
par exemple ; on aimerait pour afficher une Matrice M, utiliser :
cout< <M ;
et pour saisir ou remplir la Matrice M qu’on puisse utiliser :
cin > >M ;
Il faut savoir que :
cout est un objet prédéfini de la classe ostream,
operator< < est surchargé pour les types de bases,
cin est un objet prédéfini de la classe istream,
operator> > est surchargé pour les types de bases.

Prof. Karim Rhofir C++ & POO


Surcharge d’opérateurs

Surcharge des opérateurs < < et > > (suite)


Opérateurs prenant un flot (stream) en premier argument ,ils
doivent être surchargés comme fonction amie obligatoirement.
ostream & operator « (ostream &, MaClasse &) ;
istream & operator » (istream &, MaClasse &) ;
La valeur de retour doit être obligatoirement un flux ;càd égale
à la référence du du type du premier argument, pour pouvoir
afficher en série ou saisir en série :
cout«M«N«. . . ;
ou en notation fonctionnelle :
operator«(operator«(cout,M),N) ;

Prof. Karim Rhofir C++ & POO


Surcharge d’opérateurs

Surcharge des opérateurs < < et > >, exemple :


On va surcharger ces opérateurs pour la classe Point :
class Point {
double x , y ;
public :
Point ( double =0 , double =0);
friend ostream & operator < <( ostream & , Point &);
friend istream & operator > >( istream & , Point &);
};

Prof. Karim Rhofir C++ & POO


Surcharge d’opérateurs
Surcharge des opérateurs < < et > >, exemple :

/* Surcharge de l operateur < < en fonction


amie de la classe Point */
ostream & operator < <( ostream & sortie , Point & p )
{
sortie < < " ( " << p . x << " ," << p . y << " ) " ;
return sortie ;
}

/* Surcharge de l operateur > > en fonction


amie de la classe Point */
istream & operator > >( istream & entree , Point & p )
{
entree > > p .x > > p . y ; // saisie simple
return entree ;
}

Prof. Karim Rhofir C++ & POO


Surcharge d’opérateurs

Surcharge des opérateurs < < et > >, exemple :


A l’utilisation :
int main (){
Point B ;
cout << " donnez ␣ un ␣ point ␣ : ␣ " << endl ;
cin >> B ;
cout < < " Affichage ␣ du ␣ point ␣ : ␣ " <<B < < endl ;
}

Prof. Karim Rhofir C++ & POO

Vous aimerez peut-être aussi