0% ont trouvé ce document utile (0 vote)
16 vues42 pages

CH 5

Le chapitre traite des patrons (templates) et des fonctions amies en C++. Les patrons permettent de créer des fonctions et des classes génériques, facilitant la réutilisabilité du code sans redondance, tandis que les fonctions amies permettent à des fonctions externes d'accéder aux membres privés d'une classe. Des exemples concrets illustrent l'utilisation des templates pour définir des fonctions et des classes paramétrées par des types de données.

Transféré par

Eliza Beth
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
16 vues42 pages

CH 5

Le chapitre traite des patrons (templates) et des fonctions amies en C++. Les patrons permettent de créer des fonctions et des classes génériques, facilitant la réutilisabilité du code sans redondance, tandis que les fonctions amies permettent à des fonctions externes d'accéder aux membres privés d'une classe. Des exemples concrets illustrent l'utilisation des templates pour définir des fonctions et des classes paramétrées par des types de données.

Transféré par

Eliza Beth
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Chapitre 5 :

❑Patrons et amies " Fonctions et Classes "


❑Surcharge d'opérateurs

1
PATRONS ET AMIES "
FONCTIONS ET CLASSES "

2
Les patrons « Template »
❑Parmi les techniques pour améliorer la réutilisabilité des morceaux de
code, nous trouvons la notion de généricité.
❑Cette notion permet d’écrire du code générique en paramétrant des fonctions
et des classes par un type de données.
❑Un module générique n’est alors pas directement utilisable : c’est plutôt un
modèle, patron (template) de module qui sera «instancié» par les types de
paramètres qu’il accepte.
❑Dans la suite nous allons montrer comment C++ permet, grâce à la notion de
patron de fonctions, de définir une famille de fonctions paramétrées par un ou
plusieurs types, et éventuellement des expressions.
❑ D'une manière comparable, C++ permet de définir des "patrons de classes". Là
encore, il suffira d’écrire une seule fois la définition de la classe pour que le
compilateur puisse automatiquement l'adapter à différents types.
3
Les patrons « Template »
Patrons de fonctions
Pour illustrer les patrons de fonctions, prenons un exemple concret : une fonction min qui
accepte deux paramètres et qui renvoie la plus petite des deux valeurs qui lui est fournie.
On désire bénéficier de cette fonction pour certains types simples disponibles en C++ (int,
char, float). Les notions que nous avons vu en C++ jusqu’à maintenant ne nous permettent
de résoudre ce problème qu’avec une seule solution. Cette solution est d’utiliser la
surcharge et de définir trois fonctions min, une pour chacun des types considérés.
❑Exemple :
int min (int a, int b) {
if ( a < b)
return a ; // return ((a < b)? a : b);
else
return b ;
} 4
Les patrons « Template »
Patrons de fonctions
float min (float a, float b) {
if ( a < b)
return a ;
else
return b ;
}
char min (char a, char b) {
if ( a < b)
return a ;
else
return b ;
}
5
Les patrons « Template »
Patrons de fonctions
❑Définition des fonctions min grâce à la surcharge: lors d’un appel à la
fonction min, le type des paramètres est alors considéré et l’implantation
correspondante est finalement appelée. Ceci présente cependant quelques
inconvénients :
❖La définition des 3 fonctions (perte de temps, source d’erreur) mène à
des instructions identiques, qui ne sont différenciées que par le type
des variables qu’elles manipulent.
❖Si on souhaite étendre la définition de cette fonction à de nouveaux types, il
faut définir une nouvelle implantation de la fonction min par type considéré.
❑Une autre solution est de définir une fonction template, c’est-à-dire générique.
Cette définition définit en fait un patron de fonction, qui est instancié par un
type de données (ici le type T) pour produire une fonction par type manipulé.
6
Les patrons « Template »
Patrons de fonctions
Exemple :
template <class T> // T est le paramètre de modèle
T min (T a, T b) {
if ( a < b)
return a;
else
return b;
}
int main(){
int a = min(1, 7); // int min(int, int)
float b = min(10.0, 25.0); // float min(float, float)
char c = min(’z’, ’c’); // char min(char, char)
return 0;
}
7
Les patrons « Template »
Patrons de fonctions
❑Définition de la fonction min générique : il n’est donc plus nécessaire de
définir une implantation par type de données. On définit donc bien plus
qu’une fonction, on définit une méthode permettant d’obtenir une certaine
abstraction en s’affranchissant des problèmes de type.
Remarques :
❑Il est possible de définir des fonctions template acceptant plusieurs
types de données en paramètre. Chaque paramètre désignant une classe est
alors précédé du mot-clé class, comme dans l’exemple :
template <class T, class U> ....
❑Chaque type de données paramètre d’une fonction template doit être utilisé
dans la définition de cette fonction.
❑Pour que cette fonctionnalité soit disponible, les fonctions génériques
doivent être définies au début du programme ou dans des fichiers d’interface
(fichiers .h). 8
Les patrons « Template »
Classe template : patron de classes
❑Il est possible, comme pour les fonctions, de définir des classes template,
c’est-à-dire paramétrées par un type de données. Cette technique évite ainsi de
définir plusieurs classes similaires pour décrire un même concept appliqué à
plusieurs types de données différents. Elle est largement utilisée pour définir
tous les types de containers (comme les listes, les tables, les piles, etc.), mais
aussi des algorithmes génériques par exemple.
❑La syntaxe permettant de définir une classe template est similaire à celle qui
permet de définir des fonctions template.
❑Exemple :
int x, y ;
public :
point (int abs=0, int ord=0) ;
void affiche () ;
// ..... } ; 9
Les patrons « Template »
Classe template : patron de classes
❑Lorsque nous procédons ainsi, nous imposons que les coordonnées d'un point
soient de valeurs de type int. Si nous souhaitons disposer de points à
coordonnées d'un autre type (float, double, long ...), nous devons définir une
autre classe en remplaçant simplement, dans la classe précédente, le mot clé
int par le nom de type voulu.
❑Ici encore, nous pouvons simplifier considérablement les choses en
définissant un seul patron de classe de cette façon:
template <class T> class point {
Tx,y;
public :
point (T abs=0, T ord=0) ;
void affiche () ;
};
10
Les patrons « Template »
Classe template : patron de classes
❑Comme dans le cas des patrons de fonctions, la mention template <class T>
précise que l'on a affaire à un patron (template) dans lequel apparaît un
paramètre de type nommé T ;
❑La définition de notre patron de classes n'est pas encore complète puisqu'il y
manque la définition des fonctions membres, à savoir le constructeur point et
la fonction affiche().
❑Pour ce faire, la démarche va légèrement différer selon que la fonction
concernée est en ligne ou non. Voici par exemple comment pourrait être défini
notre constructeur en ligne:
point (T abs=0, T ord=0) {
x = abs ; y = ord ;
}

11
Les patrons « Template »
Classe template : patron de classes
❑En revanche, lorsque la fonction est définie en dehors de la définition de la
classe, il est nécessaire de rappeler au compilateur :
❖que, dans la définition de cette fonction, vont apparaître des paramètres de type ;
pour ce faire, on fournira à nouveau la liste de paramètre sous la forme:
template <class T>
❖le nom du patron concerné. Par exemple, si nous définissons ainsi la
fonction affiche, son nom sera: point<T>::affiche ()
❑En définitive, voici comment se présenterait l'en-tête de la fonction
affiche si nous le définissions ainsi en dehors de la classe :
template <class T>
void point<T>::affiche ()
❑En toute rigueur, le rappel du paramètre T à la suite du nom de patron (point)
est redondant puisqu’il a déjà été spécifié dans la liste de paramètres suivant
le mot clé template. 12
Les patrons « Template »
Classe template : patron de classes
❑Voici ce que pourrait être finalement la définition de notre patron de classe
point :
template <class T> class point // Création d'un patron de classe
{ Tx,y;
public :
point (T abs=0, T ord=0)
{ x = abs ; y = ord ; }
void affiche () ;
};
template <class T> void point<T>::affiche ()
{ cout << "Paire : " << x << " " << y << "\n" ; }

13
Les patrons « Template »
Utilisation d’un patron de classes
❑Comme pour les patrons de fonctions, l’instanciation de tels patrons
est effectuée automatiquement par le compilateur selon les déclarations
rencontrées. Après avoir créé ce patron, une déclaration telle que:
point <int> a;
❑conduit le compilateur à instancier la définition d'une classe point dans
laquelle le paramètre T prend la valeur int. Autrement dit, tout se passe
comme si nous avions fourni une définition complète de cette classe. Si
nous déclarons :
point <float> ad ;
❑le compilateur instancie la définition d'une classe point dans laquelle le
paramètre T prend la valeur float, exactement comme si nous avions fourni
une autre définition complète de cette classe.

14
Les patrons « Template »
Utilisation d’un patron de classes
❑Si nous avons besoin de fournir des arguments au constructeur, nous
procéderons de façon classique comme dans :
point <int> a (3, 5) ;
point <float> ad (1.5, 9.6) ;
❑Si nous faisons abstraction de la signification des paramètres (coordonnées
d’un point) et nous les déclarons comme des caractères ou chaînes de
caractères, le compilateur ne signalera pas d’incohérence et la fonction
affiche() remplacera x et y par les arguments, comme le montre l’exemple
récapitulatif.

15
Les patrons « Template »
Utilisation d’un patron de classes
Voici un programme complet comportant :
❑la création d'un patron de classes point dotée d’un constructeur en ligne et
d’une fonction membre (affiche) non en ligne,
❑la création d’un patron de fonctions min (en ligne dans la patron de classes)
qui retourne le minimum des arguments,
❑un exemple d'utilisation (main).

16
Les patrons « Template »
#include <iostream>
#include <string>
using namespace std ;
template <class T> class point // Création d'un patron de classe
{ Tx;
Ty;
public :
point (T abs=0, T ord=0)
{ x = abs ; y = ord ; }
void affiche () ;
T min ()
{ if ( x < y)
return x;
else
return y;
}
};
17
Les patrons « Template »
template <class T> void point<T>::affiche ()
{ cout << "Paire : " << x << " " << y << "\n" ; }
void main ()
{ point <int> ai (3, 5) ; // T prend la valeur int pour la classe point
[Link]() ;
cout << " Min : ... " << [Link]() << endl;
point <char> ac ('z', 't') ; [Link]() ;
cout << " Min : ... " << [Link]() << endl;
point <double> ad (1.5, 9.6) ; [Link]() ;
cout << " Min : ... " << [Link]() << endl;
point <string> as ("Salut", " A vous") ; [Link]() ;
cout << " Min : ... " << [Link]() << endl;
}

18
Les patrons « Template »
Remarque :
Il faut noter aussi que le nombre de paramètres n'est pas limité à 1, on peut en
avoir
plusieurs :

template < class A, class B, class C, ... >


class MaClasse {
// ...
public:
// ...
};

19
Les patrons « Template »
❑L’exemple suivant montre comment implémenter les fonctions de la classe
template.
template <class T, class T1, class T2> class Etudiant {
T Nom, Prenom;
T1 Id;
T2 Age;
public:
//...
T getNom()
{return nom;}
T1 getId()
{return Id;}
T2 getAge();
void Saisie();
void affiche();
//...
}; 20
Les patrons « Template »
template <class T, class T1, class T2> T2 Etudiant<T,T1,T2>::getAge()
{ return Age; }
template <class T, class T1, class T2> void Etudiant<T,T1,T2>::affiche ()
{ cout << "Data : " << Nom << " " << Id << " " << Age <<"\n" ; }

21
Fonctions amies
❑Comment faire pour qu’une fonction f() et/ou une classe B puisse accéder
aux données membres privées d’une classe A ?
❑Exemple :
class ratio
{ private:
int num, den ;
public:
ratio(int n, int d);
void affiche();
float val_reel();
}
ratio somme (ratio r1, ratio r2);

22
Fonctions amies
Solution:
❑Rendre publiques les données membres des classes.
❖Inconvénient: on perd leurs protections.
❑Ajout de fonctions d’accès aux membres privés.
❖Inconvénient : temps d’exécution pénalisant.
❑Fonctions amies : Il est possible de déclarer qu’une ou plusieurs fonctions
(extérieurs à la classe), sont des « amies » ; une telle déclaration d’amitié les
autorise alors à accéder aux données privées au même titre que n’importe
quelle fonction membre. L’avantage de cette méthode est de permettre le
contrôle des accès au niveau de la classe concernée.

23
Fonctions amies
Exemple de déclaration d’une fonction amie:
class A{
private :
int i ;
friend class B ;
friend void f();
}
class B
{
//tout ce qui appartient à B,
//peut se servir des données membres privés de A
// comme si elle était de A.
...
}
void f(A& a)
{ a.i = 10 ; }
24
Fonctions amies
Situation d’amitiés

❑Fonction indépendante amie d’une classe.


❑Fonction membre d’une classe amie d’une autre classe.
❑Fonction amie de plusieurs classes
❑Toutes les fonctions membres d’une classe, amies d’une autre classe

25
Fonctions amies
Situation d’amitiés
Exemple de fonction indépendante amie d’une classe
class point
{ private :
int x,y ;
public :
point (int abs= 0, int ord = 0)
{ x= abs ;
y= ord ;
};
// déclaration d’une fonction amie indépendante
friend int coincide (point p, point q) ;
};
26
Fonctions amies
Situation d’amitiés
Exemple de fonction indépendante amie d’une classe
int coincide (point p, point q) {
if ((p.x == q.x) && (p.y == q.y) )
return (1);
else
return (0);
};
void main() {
point a(1,0), b (1), c ;
if ( coincide (a,b) )
cout<< "A coincide avec B”<<endl;
else
cout<<”A et B sont différents”<<endl;
}; 27
Fonctions amies
Fonction membre d’une classe amie d’une autre classe
On considère deux classes A et B
❖int f(char, A) fonction membre de B
❖f doit pouvoir accéder aux membres privés de A, elle sera déclarée amie au
sein de la classe A :
friend int B :: f(char, A) ;
❑Exemple :
class A
{ private :
// partie privée
public :
// partie publique
friend int B :: f (char, A) ;
...
}; 28
Fonctions amies
Fonction membre d’une classe amie d’une autre classe
class B
{ private :
// partie privée
public :
// partie publique
int f (char, A) ;
...
...
};
int B :: f (char, A) ;
{ // on a ici accès aux membres privés de tout objet de type A
};

29
Fonctions amies
Fonction amie de plusieurs classes
❑Rien n’empêche qu’une même fonction (indépendante ou membre)
fasse l’objet de déclaration d’amitié dans différentes classes.
❑Toutes les fonctions d’une classe sont amies d’une autre classe
friend class B ; // dans la classe A

30
Fonctions amies
Toutes les fonctions membres d’une classe, amie d’une autre classe
❑C’est une généralisation du cas précédent. On pourrait d’ailleurs
effectuer autant de déclarations d’amitié qu’il n’y a de fonctions concernées.
Mais il est plus simple d’effectuer une déclaration globale.
❑Ainsi pour dire que toutes les fonctions membres de la classe B sont amies
de la classe A, on placera, dans la classe A, la déclaration :
friend class B ;
Exemple :
class A
{ // partie privée
......
// partie publique
friend class B;
......
}; 31
Fonctions amies
Toutes les fonctions membres d’une classe, amie d’une autre classe
Exemple :
class A
{ // partie privée
......
// partie publique
friend class B;
......
};
class B
{ ......
//on a accès totale aux membres privés de tout
//objet de type A
......
}; 32
SURCHARGE
D'OPÉRATEURS

33
Surcharge d’opérateurs
❑C++ autorise la surdéfinition de fonctions, qu’il s’agisse de fonctions
membres ou de fonctions indépendantes.
❑Exemple:
class ratio
{ private :
int num, den ;
public :
ratio ( n=0, d=1) ;
ratio(n) ;
};
Attribuer le même nom à des fonctions différentes, lors de l’appel, le
compilateur fait le choix de la bonne fonction suivant le nombre et les types
d’arguments.

34
Surcharge d’opérateurs
❑C++ permet aussi la surdéfinition d’opérateurs
❑Exemple :
a+b ;
❑Le symbole + peut designer suivant le type de a et b :
❖L’addition de deux entiers
❖Addition de deux réels
❖Addition de deux doubles.
❖+ est interprété selon le contexte.
❑En C++ on peut surdéfinir n’importe quel opérateur existant (unaire ou
binaire). Ce qui va nous permettre de créer par le biais de classes, des types
avec des opérateurs parfaitement intégrés.
❑On peut donner une signification à des expressions comme a+b, a-b, a*b et
a/b pour la classe ratio
35
Surcharge d’opérateurs
Mécanisme de surdéfinition
Considérons la classe point :
class point
{ private :
int x, y ;
public :
// partie publique
...
};
❑Supposons que nous souhaitons définir l’opérateur (+) afin de donner une
signification à l’expression a+b, tels que, a et b sont de type point.
❑On considère que la somme de deux points est un point dont les coordonnées
sont la somme de leurs coordonnées.

36
Surcharge d’opérateurs
Mécanisme de surdéfinition
❑Pour surdéfinir (surcharger) cet opérateur en C++, il faut définir une fonction
de nom : Operatorxx où xx est le symbole de l’opérateur.
❑La fonction operator+ doit disposer de deux arguments de types point et
fournir une valeur de retour de même type.
❑Cette fonction peut être définie en tant que fonction membre de la classe
(méthode) ou fonction indépendante (fonction amie).

37
Surcharge d’opérateurs
Surcharge d’opérateurs par des fonctions amies
❑Le prototype de notre fonction sera : point operator+ (point, point)
❑Les deux opérandes correspondent aux deux opérandes de l’opérateur +
❑Le reste du travail est classique :
❖Déclaration d’amitié
❖Définition de la fonction
❑Exemple :
class point
{ private :
int x, y ;
public :
point (int abs =0, ord =0) ;
friend point operator+ (point , point) ;
void afficher( );
}; 38
Surcharge d’opérateurs
Surcharge d’opérateurs par des fonctions amies
point operator+ (point a, point b) {
point p;
p.x =a.x +b.x;
p.y = a.y + b.y;
return p;
}
void main() {
point a (1,2);
point b (2,5);
point c;
c= a+b; [Link]();
c= a+b+c; [Link]();
}
❑On a surchargé l’opérateur + pour des objets de type point en employant une
fonction amie. 39
Surcharge d’opérateurs
Surcharge d’opérateurs par des fonctions membres
❑Dans ce cas, le premier opérande sera l’objet ayant appelé la fonction
membre
❑Exemple :
❖L’expression a+b sera interprétée par le compilateur comme [Link]+ (b) ;
❖Le prototype de notre fonction membre est alors: point operator+ (point);
❑Exemple:
class point
{ private:
int abs, ord;
public:
point (int abs, int ord);
point operator+ (point a);
void affiche();
}; 40
Surcharge d’opérateurs
Surcharge d’opérateurs par des fonctions membres
point point ::operator+ (point a);
{ point p;
p.x = x + a.x;
p.y = y + a.y;
return (p) ;
}
void main()
{
point a (1,2);
point b (2,5);
point c;
c= a+b; [Link]();
c= a+b+c; [Link]();
} 41
Surcharge d’opérateurs
Surcharge en général
❑On a vu un exemple de surdéfinition de l’opérateur + lorsqu’il reçoit deux
opérandes de type point. Ces de deux façons :
❖fonctions amies
❖fonctions membres
❑Remarques :
❖Il faut se limiter aux opérateurs existants. Le symbole qui suit le mot clé
operator doit obligatoirement être un opérateur déjà défini pour les types de
base. Il n’est pas permis de créer de nouveaux symboles.

42

Vous aimerez peut-être aussi