Vous êtes sur la page 1sur 62

‫المدرسة الوطنية للمهندسين بتونس‬

École Nationale d’Ingénieurs de Tunis

Chap-2 : Les Classes en C++

Kamel Hamrouni
Abir Gallas
Introduction

 Objectif : Concevoir des programmes sous la forme d’objets qui


s’échangent des messages au lieu d’avoir une liste de sous-programmes
qui se partagent des données. Chaque objet aura ses propres données
et ses propres programmes spécialisés dans la manipulation de ses
données. Les données seront inaccessibles au monde extérieur qui ne
connaît l’objet que par l’intermédiaire d’un certain nombre de points
d’accès. C’est le concept d’encapsulation des données :
Fonctions Interface
internes d’utilisation

Données

2
Introduction (2)
Un objet sera caractérisé par plusieurs notions :
 Les attributs : qui sont les données de l’objet.
 Les méthodes : appelées aussi fonctions membres : Elles caractérisent le
comportement de l’objet c’est à dire l’ensemble des actions que l’objet peut
réaliser.
 L’identité : chaque objet doit avoir une identité qui permet de le distinguer
des autres objets.
La structure d’un objet fera l’objet d’une déclaration au sein de ce qui est
appelé « classe ». Plusieurs objets peuvent avoir la même structure donc issus
d’une même classe. Par exemple, la structure d’une voiture (moteur, roues,
cabine,…) fera l’objet d’une classe alors qu’une mercedes-200 est un objet de
type voiture.
Les avantages d’une telle conception sont :
Protection des données, Meilleure structuration du programme,
Maintenance plus facile.
3
Définition d’une classe
La classe décrit le modèle structurel d’un objet. Elle est
composée de :
 Ensemble des attributs (ou champs ou données membres)
décrivant sa structure
 Ensemble des opérations (ou méthodes ou fonctions
membres) qui lui sont applicables.

Une classe en C++ est une structure qui contient :


 Des fonctions membres
 Des données membres

Les mots réservés public et private délimitent les sections visibles


par l’application.

4
Définition d’une classe (2)
Exemple

class Avion
{ private : // membres privées

char immatriculation[6], *type; // données membres privées


float poids;
void erreur(char *message); // fonction membre privée

public : // fonctions membres publiques

void init(char [ ], char *, float);


void affiche();

}; // n’oubliez pas ce ; après l’accolade

5
Droits d’accès
L’encapsulation consiste à masquer l’accès à certains attributs
et méthodes d’une classe. Elle est réalisée à l’aide des mots clés :

 private: les membres privés ne sont accessibles que par les


fonctions membres de la classe. La partie privée est aussi appelée
réalisation.
 protected: les membres protégés sont comme les membres
privés. Mais ils sont aussi accessibles par les fonctions membres
des classes dérivées (voir l’héritage).
 public: les membres publics sont accessibles par tous. La partie
publique est appelée interface.

Les mots réservés private, protected et public peuvent figurer


plusieurs fois dans la déclaration de la classe. Le droit d’accès ne
change pas tant qu’un nouveau droit n’est pas spécifié.
6
Types de Classes
Les deux structures « struct » et « union » introduites par le langage C et la structure
« class » introduite par le C++ sont considérées comme des classes. Mais c’est la
troisième qui est la plus utilisée.

 struct Classe1 { /* ... */ };


Tous les membres sont par défaut d’accès public, le contrôle d’accès est modifiable.
Cette structure est conservée pour pouvoir compiler des programmes écrits en C

Exemple
struct Date
{ // méthodes publiques (par défaut)
void set_date(int, int, int);
void next_date();
// autres méthodes ....
private : // données privées
int jour, mois, an;
};

7
Types de Classes (2)

 union Classe2 { /* ... */ };


Tous les membres sont d’accès public par défaut le contrôle
d’accès n’est pas modifiable

class Classe3 { /* ... */ };


Tous les membres sont d’accès private (par défaut). Le contrôle
d’accès est modifiable. C’est cette dernière forme qui est utilisée
en programmation objet C++ pour définir des classes.

8
Recommandation de style

Pour écrire des programmes claires et faciles à relire et à


comprendre, il vaut mieux adopter quelques conventions de
style. On pourrait par exemple choisir de mettre :

 La première lettre du nom de la classe en majuscule


 La liste des membres publics en premier
 Les noms des méthodes en minuscules

9
Définition des fonctions membres
En général, la déclaration d’une classe contient simplement les prototypes des
fonctions membres de la classe. Les fonctions membres sont définies dans un
module séparé ou plus loin dans le code source.

 Déclaration à l’extérieur de la classe


class Avion
{ private :
char immatriculation[6], *type;
float poids;
void erreur(char *message);
public :
void init(char [ ], char *, float); // prototype des fonctions membres
void affiche();
};

10
Définition des fonctions membres (2)
void Avion::init(char m[ ], char *t, float p)
{ strcpy(immatriculation, m);
type = new char [strlen(t)+1];
strcpy(type, t);
poids = p;
}
void Avion::affiche()
{ cout << immatriculation << " " << type;
cout << " " << poids << endl;
}

Syntaxe générale :
type_valeur_retournée Classe::nom_fonction ( paramètres_formels )
{ // corps de la fonction }

11
Définition des fonctions membres (3)
 Déclaration à l’intérieur de la classe
La définition de la méthode peut avoir lieu à l’intérieur de la déclaration de la classe.
Dans ce cas, ces fonctions sont automatiquement traitées par le compilateur comme
des fonctions inline. Une fonction membre définie à l’extérieur de la classe peut être
aussi qualifiée explicitement de fonction inline.
Exemple
class Nombre
{ private : int nbre;
public :
void setnbre(int n) { nbre = n; } // fonction inline
int getnbre() { return nbre; } // fonction inline
void affiche();
};
void Nombre::affiche()
{ /* fonction inline : La visibilité d’une fonction inline est restreinte au
module dans lequel elle est définie. */
12 cout << "Nombre = " << nbre << endl; }
Instanciation d’une classe
De façon similaire à une struct ou à une union, le nom de la classe représente
un nouveau type de donnée. On peut donc définir des variables de ce
nouveau type; on dit alors que vous créez des objets ou des instances de
cette classe.

Exemple

Avion av1; // une instance simple (statique)


Avion *av2; // un pointeur (non initialisé)
Avion compagnie[10]; // un tableau d’instances
av2 = new Avion; // création (dynamique) d’une instance

13
Utilisation des objets
Après avoir créé une instance (de façon statique ou dynamique)
on peut accéder aux attributs et méthodes de la classe. Cet
accès se fait comme pour les structures à l’aide de l’opérateur .
(point) ou -> (tiret supérieur).

Exemple
av1.init("FGBCD", "TB20", 1.47);
av2->init("FGDEF", "ATR 42", 80.0);
compagnie[0].init("FEFGH","A320", 150.0);
av1.affiche();
av2->affiche();
compagnie[0].affiche();
av1.poids = 0; // erreur, poids est un membre privé
14
Exemples
 Nombre complexe

Un objet complexe doit contenir deux composantes réelles et


doit répondre aux fonctions suivantes :
 initialiser un nombre complexe
 ajouter deux nombres complexes
 soustraire deux nombres complexes
 multiplier deux nombres complexes
 afficher un nombre complexe
 etc.

 Attributs : Deux réels : x et y


 Méthodes : Initialiser, Ajouter, Soustraire, Multiplier, afficher

15
Exemples (2)
class complexe
{ public:
float x,y ;
void init (float a=0, float b = 0);
void ajouter (complexe z);
void soustraire (complexe z);
void multiplier (complexe z);
void afficher ( );
};
void complexe::init(float a , float b)
{ x = a;
y = b ;}
16
Exemples (3)
void complexe::ajouter(complexe z)
{ x = x + z.x ;
y = y + z.y ; }
void complexe ::soustraire(complexe z)
{ x = x - z.x ;
y = y - z.y ; }
void complexe ::multiplier(complexe z)
{ x = x*z.x - y*z.y ;
y = x*z.y + y*z.x ; }
void complexe::afficher( )
{ if y>=0
cout <<x<< « +i »<<y ;
else
cout <<x<< « -i »<<-y ;
}

17
Exemples
 Pile d’entiers

Un objet Pile doit répondre aux fonctions suivantes :


 Initialiser une pile
 Empiler un élément sur la pile
 Dépiler un élément de la pile

Pour cet exemple, nous allons supposer que les éléments à empiler
sont de type entier et nous allons utiliser un tableau linéaire pour
l’implémentation.

18
Exemples (2)
#include <iostream.h>
class pile
{ int tab [100]; // Tableau pour contenir les éléments
int k; // indice dans tab de la première position libre
int max; // nombre maximum de places dans la pile

public:
void init ();
int push (int x);
int pop (int &x);
int full ();
int empty ();
};

19
Exemples (3)
//----------------- init -----------------------------
void pile::init ()
{ k=0 ;
max = 100;
}
//----------------- full -----------------------------
int pile::full()
{ return (k >= max ) ; }

//----------------- empty ---------------------------


int pile::empty()
{ return (k == 0 ) ; }

20
Exemples (4)
//----------------- push -----------------------------
int pile::push (int x)
{ if (!full())
{ tab[k++] = x;
return 1;
} else return 0;}
//----------------- pop -----------------------------
int pile::pop (int &x)
{ if ( !empty () )
{ x= tab[--k];
return 1;
}else
return 0;}

/*Le programme main comprend la définition d’une classe Pile et un


programme de test qui crée deux piles p1 et p2, empile dessus des valeurs
entières et les dépiler pour vérifier les opérations push et pop. */
21
Exemples (5)
void main()
{ pile p1, p2;
int i;
p1.init ();
p2.init ();
for (i= 1; i < 10 ; k++)
p1.push (i);
for (i=200; i<215; i++ )
p2.push (i);
while ( p1.pop (i))
cout << " Vidange de p1: " << i << "\n";
while ( p2.pop (i))
cout << " Vidange de p2: " << i << "\n"; }

22
Fonctions constantes

 Certaines méthodes d’une classe ne doivent (ou ne


peuvent) pas modifier les valeurs des données membres
de la classe, ni retourner une référence non constante ou
un pointeur non constant d’une donnée membre. On dit
que ce sont des fonctions membres constantes.

 Ce type de déclaration renforce les contrôles effectués


par le compilateur et permet donc une programmation
plus sûre sans coût d’exécution.

23
Fonctions constantes (2)
Exemple
class Nombre
{ private :
int nbre;
public :
void setnbre(int n) { nbre = n; }
// méthodes constantes
int getnbre() const { return nbre; }
void affiche() const;
};
inline void Nombre::affiche() const
{ cout << "Nombre = " << nbre << endl; }
24
Fonctions constantes (3)
Une fonction membre const peut être appelée sur des objets
constants ou pas, alors qu’une fonction membre non constante ne
peut être appelée que sur des objets non constants.

Exemple
const Nombre n1; // une constante
n1.affiche(); // OK
n1.setnbre(15); /* ERREUR: seule les fonctions
const peuvent être appelées pour un objet constant*/
Nombre n2;
n2.affiche(); // OK
n2.setnbre(15); // OK

25
Surcharge d’une méthode par une
méthode constante
Une méthode déclarée comme constante permet de surcharger une méthode
non constante avec le même nombre de paramètres du même type.
Exemple
class String
{ private :
char *str;
public :
void init(char *ch = "");
// etc ...
char nieme(int n); // (1)
char nieme(int n) const; // (2)
// etc...
};
S’il n’y a pas le qualificatif const dans la deuxième méthode, le compilateur
génère
26 une erreur ("String::nieme() cannot be redeclared in class").
Surcharge d’une méthode par une
méthode constante (2)
Cette façon de faire permet d’appliquer la deuxième méthode
nieme() à des objets constants et la première méthode nieme() à
des objets variables :

void main()
{ String ch1;
ch1.init("toto");
const String ch2;
ch2.init("coco");
cout << ch1.nieme(1); // appel de la méthode (1)
cout << ch2.nieme(1); // appel de la méthode (2)
}

27
Constructeurs
Les données membres d’une classe ne peuvent pas être initialisées;
il faut donc prévoir une méthode d’initialisation de celles-ci
(voir la méthode init de l’exemple précédent). Si l’on oublie
d’appeler cette fonction d’initialisation, le reste n’a plus de sens
et il se produira très certainement des surprises fâcheuses dans
la suite de l’exécution. De même, après avoir fini d’utiliser l’objet,
il est bon de prévoir une méthode permettant de détruire l’objet
(libération de la mémoire dynamique ...).

 Le constructeur est une fonction membre spécifique de la


classe qui est appelée implicitement à l’instanciation de l’objet,
assurant ainsi une initialisation correcte de l’objet. Ce
constructeur est une fonction qui porte comme nom, le nom de
la classe et qui ne retourne pas de valeur (pas même un void).

28
Constructeurs (2)

Il existe trois types de constructeurs :


 Constructeur par défaut
 Constructeur à un ou plusieurs paramètres
 Constructeur de copie

Une classe peut avoir plusieurs constructeurs.

29
Constructeur par défaut
On appelle constructeur par défaut un constructeur n’ayant pas de
paramètre ou ayant des valeurs par défaut pour tous les paramètres. Si le
concepteur de la classe ne spécifie pas de constructeur, le compilateur
génèrera un constructeur par défaut.

Exemple
class Nombre
{ public :
Nombre(); // constructeur par défaut
// ...
private :
int i;
};
Nombre::Nombre()
{ i = 0; }

30
Constructeur à un paramètre
class Nombre
{ public :
Nombre(int i=0); // constructeur à un paramètre
// ...
private :
int i;
};
Nombre::Nombre(int a)
{
i = a;
}
31
Constructeur avec paramètres et
surcharge des constructeurs
Comme les autres fonctions, les constructeurs peuvent être
surchargés.

class Nombre
{ public :
Nombre(); // constructeur par défaut
Nombre(int a); // constructeur à 1 paramètre
private :
int i;
};

Le constructeur est appelé à l’instanciation de l’objet. Il n’est


donc pas appelé quand on définit un pointeur sur un objet.

32
Constructeur avec paramètres et
surcharge des constructeurs (2)
Exemple
Nombre n1; //correct, appel du constructeur par défaut
Nombre n2(10); //correct, appel du constructeur à 1 paramètre
Nombre *ptr1, *ptr2; //correct, pas d’appel aux constructeurs
ptr1 = new Nombre; //appel au constructeur par défaut
ptr2 = new Nombre(12); //appel du constructeur à 1 paramètre
Nombre tab1[10]; // chaque objet du tableau est initialisé
// par un appel au constructeur par défaut
Nombre tab2[3] = { Nombre(10), Nombre(20), Nombre(30) };
//initialisation des 3 objets du tableau
//par les nombres 10, 20 et 30
33
Destructeurs
De la même façon que pour les constructeurs, le destructeur
est une fonction membre spécifique de la classe qui est appelée
implicitement à la destruction de l’objet. Ce destructeur est une
fonction qui :
 porte comme nom, le nom de la classe précédé du caractère
(tilda ~)
 ne retourne pas de valeur (pas même un void )
 n’accepte aucun paramètre (le destructeur ne peut donc pas
être surchargé)

34
Destructeurs (2)
Exemple
class Exemple
{ public :
// ...
~Exemple();
private :
// ...
};
Exemple::~Exemple()
{ // ... }

Comme pour le constructeur, le compilateur génèrera un destructeur


par défaut si le concepteur de la classe n’en spécifie pas un.

35
Exemple : Pile d’entiers avec
constructeur et destructeur
Dans cette version de l’implémentation d’une pile, nous allons définir un constructeur
qui aura pour rôle d’allouer un espace mémoire et d’initialiser l’indice sommet. Les
autres fonctions restent inchangées.
#include <iostream.h>
class pile
{ int *tab ; // pointeur sur le début de la pile
int sommet ; // indice première position libre
int max ; // nombre max de places
public:
pile ( int taille = 100); // constructeur
~pile ( ) ; // destructeur
int full ();
int empty ();
int push (int x);
int pop (int &x);
};
36
Exemple : Pile d’entiers avec
constructeur et destructeur (2)
//----------------- constructeur---------------------
pile::pile ( int taille)
{ tab= new int [taille] ;
sommet = 0
max = taille ;
}
//----------------- destructeur---------------------
pile::~pile ( )
{ delete [ ] tab;
}

37
Exemple : Pile d’entiers avec
constructeur et destructeur (3)
//----------------- full -----------------------------
int pile::full()
{ return (sommet >= max ) ; }

//----------------- empty ---------------------------


int pile::empty()
{ return (sommet == 0 ) ; }

38
Exemple : Pile d’entiers avec
constructeur et destructeur (4)
//----------------- push -----------------------------
int pile::push (int x)
{ if (!full())
{ tab[sommet] = x;
sommet++; return 1;
} else return 0;
}
//----------------- pop -----------------------------
int pile::pop (int &x)
{ if ( !empty () )
{ sommet--;
x= tab[sommet]; return 1;
}else
return 0;}

39
Exemple : Pile d’entiers avec
constructeur et destructeur (5)
//----------------- programme main --------------
void main()
{ pile p1; // p1 aura 100 éléments
pile p2(50); // p2 aura 50 éléments
int k;
for (k= 1; k < 10 ; k++)
p1.push (k);
for (k=200; k< 215; k++ )
p2.push (k);
while ( p1.pop (k))
cout << " Vidange de p1: " << k << "\n";
while ( p2.pop (k))
cout << " Vidange de p2: " << k << "\n";
}

40
Constructeur de copie
 Présentation du problème
Une variable peut être créée de quatre manières différentes :

 Déclaration : int a ;
 Par new : p = new int;
 Initialisation int b = a;
 Paramètre d’une fonction : A chaque paramètre est créée sur
la pile une variable qui recevra une copie du paramètre. Cette
variable locale sera détruite automatiquement à la sortie de la
fonction.

41
Constructeur de copie (2)
Dans les deux premiers cas, le constructeur d’une classe est
appelé automatiquement. Par contre il n’est pas appelé dans
le troisième et le quatrième cas. Le destructeur quant à lui
est appelé dans tous les cas.
 On doit créer un constructeur spécial dit
« constructeur de copie » qui sera appelé uniquement dans
le 3ème et le 4ème cas. Ce constructeur portera le même
nom que le constructeur standard mais avec un paramètre
qui devra être une référence à un objet de la même
classe :
classe ( classe & ) ;

42
Constructeur de copie (3)
Exemple
#include <iostream.h>
class bidon
{ int data;
public:
bidon (int k=0) // constructeur d'initialisation
{
data = k;
cout << "\nEntrée dans constructeur d'initialisation";
}

43
Constructeur de copie (4)
bidon ( bidon &objet)
{ // constructeur de copie
data = objet.data;
cout << "\nEntrée dans constructeur de copie";
}
~bidon()
{ // destructeur
cout << "\nEntrée dans destructeur";
}

void fonction_test( bidon ) ;

};

44
Constructeur de copie (5)
void bidon::fonction_test( bidon objet)
{
cout << "\nEntrée dans fonction_test";
data = objet.data;
}
void main()
{ bidon x(100), y(200), z=x;
int k;
x.fonction_test (y);
cin >> k;
}

45
Constructeur de copie (6)
Résultat du programme
Le programme imprimera les lignes suivantes :

Entrée dans constructeur d'initialisation // généré par bidon x(100)


Entrée dans constructeur d'initialisation // généré par bidon y(200)
Entrée dans constructeur de copie // généré par bidon z=x
Entrée dans constructeur de copie // généré par : x.fonction_test (y)
Entrée dans fonction_test
Entrée dans destructeur // destruction de l’argument objet
// à la sortie de la fonction
Entrée dans destructeur // destruction de z
Entrée dans destructeur // destruction de y
Entrée dans destructeur // destruction de x
46
Constructeur de copie (7)
class Date
{
private:
int *jour, *mois, *annee;
public:

Date(int,int,int); //Constructeur par défaut


Date (const Date &); //Constructeur de copie
~Date(); //Destructeur

47
Constructeur de copie (8)

/* Méthodes d’accès */
void DefinirDate(int j,int m,int a)
{ *jour=j; *mois=m; *annee=a; }
void LireDate() const
{ cout<<*jour<<" "<<*mois<<" "<<*annee<<endl; }

int LireJour() const { return *jour; }


int LireMois() const { return *mois; }
int LireAnnee() const { return *annee; }
};

48
Constructeur de copie (9)

49
Classes imbriquées
Il est possible de créer une classe par une relation d’appartenance : relation
« a un » ou « est composée de »  un membre d’une classe peut être un
objet d’une autre classe
Exemple : une voiture a un moteur, a des roues ...

class Moteur { /* ... */ };


class Roue { /* ... */ };
class Voiture
{ public:
// ....
private:
Moteur moteur;
Roue roue[4];
// ....
};

50
Affectation et initialisation

Le langage C++ fait la différence entre l’initialisation et


l’affectation d’une variable :

 L’initialisation est une opération qui n’a lieu qu’une fois


immédiatement après que l’espace mémoire de la variable
ait été alloué. Cette opération consiste à donner une valeur
initiale à l’objet ainsi créé.
 L’affectation consiste à modifier la valeur d’une variable
(et peut avoir lieu plusieurs fois).

51
Affectation et initialisation (2)
void main ()
{
int n = 100 ; // c’est une initialisation
n = 200 ; // c’est une affectation
//…..
}

Initialiser une variable simple est facile par contre initialiser


un objet qui est composé de membres qui peuvent eux
mêmes être des objets peut poser quelques petits
problèmes.

52
Liste d’initialisation d’un constructeur

Lorsqu’on a des classes imbriquées, il peut y avoir un


problème lors de l’appel du constructeur des différentes
classes.

class toto
{ int u ;
public :
toto ( int s=0) { u = s } ;
…..
};

53
Liste d’initialisation d’un constructeur
(2)
class truc
{ const int x;
int y;
toto z;
public:
truc(int a, int b, int c); // Constructeur de truc
~truc(); // Destructeur de truc
};
truc::truc(int a, int b, int c)
{ x=a ; // ERREUR: l’affectation à une constante est interdite
y=b // OK : affectation
// et comment initialiser l’objet membre z ???
} Comment initialiser la donnée membre constante x et appeler
le constructeur de la classe toto ?
54
Liste d’initialisation d’un constructeur
(3)
Réponse : la liste d’initialisation.
La phase d’initialisation de l’objet utilise une liste d’initialisation
qui est spécifiée dans la définition du constructeur.
Syntaxe
nom_classe::nom_constructeur( args ... ): liste_d’initialisation
{ // corps du constructeur }

Exemple
truc::truc(int a, int b, int c): x( a ) , y( b ) , z( c )
{ // rien d’autre à faire dans cet exemple }
x( a ) x = a
y( b ) y = b
z( c ) appel du constructeur de la classe toto : toto(c)

55
Le pointeur this
Toute méthode d’une classe X a un paramètre caché : le pointeur
this qui contient l’adresse de l’objet qui l’a appelé. Il est implicitement
déclaré :
 comme (pour une variable) : X * const this;
 et comme (pour un objet constant) : const X * const this;
et initialisé avec l’adresse de l’objet sur lequel la méthode est appelée.

Il peut être explicitement utilisé :


classe X
{ int i ;
public:
int f1()
{ return this->i; // équivalent à : return i ;
}
};
56
Pointeur sur des membres d’une classe
Il est possible de déclarer de l’extérieur un pointeur sur un
membre d’une classe.

Exemple
Class toto
{ public :
int a ;
// …………..
};
toto var1 ;
int *p = &var1.a ;

57
Les membres statiques
Ces membres sont utiles lorsqu’on a besoin de gérer des données communes
aux instances d’une même classe. On peut avoir des données statiques et des
fonctions statiques.
 Données membres statiques
Si l’on déclare une donnée membre comme static, elle est commune à tous
les objets. Elle existe même si aucun objet n’a été créé et elle aura la même
valeur pour toutes les instances de cette classe. Elle est accessible en
spécifiant soit le nom de l’objet soit celui de la classe.
class toto L’initialisation de cette donnée
{ static int a; membre statique se fera en dehors
int b ; de la classe et en global par une
public: déclaration :
int toto::a = 0;
toto () { a++; /* ... */ } // initialisation du membre static
~toto () { a--; /* ... */ }
};
58
Les membres statiques (2)
 Fonctions membres statiques
De même que les données membres statiques, il existe des fonctions
membres statiques. Une fonction static ne peut accéder qu’aux membres
statiques et ne peut pas être surchargée. Elle existe même s’il n’y a pas
d’instance de la classe.
class toto
{ static int a ; void main()
int b; {
public: toto x, y, z;
toto() { a++; /* ... */ } x.affiche(); //affiche 3
~toto() { a--; /* ... */ } }
static void affiche()
{cout << a << endl; }
};
int toto::a = 0; // initialisation du membre static (en global)

59
Classes et fonctions amies
Une classe peut déclarer « amie » une autre classe ou
des fonctions externes.

Une classe ou une fonction peut toucher les


membres privées ou protégés de son « ami».

 C’est le mot clé friend qui permet de déclarer l’amitié


entre classes.
 C’est une infraction aux règles d’encapsulation pour des
raisons d’efficacité.

60
Classes et fonctions amies (2)
Exemple de fonction amie
class toto
{ friend void visualiser(toto ); // fonction amie
int a ;
public :
// ...
};
void visualiser(toto n)
{ cout << n.a ;
/* je peux le faire en toute légalité parce que je suis une fonction
amie de la classe toto*/
}

61
Classes et fonctions amies (3)
Exemple de classe amie
class Fenetre { // déclaration de la classe Fenetre };
class Ecran
{ friend class Fenetre;
public:
//...
private :
//...
};

Les fonctions membres de la classe Fenetre peuvent accéder aux


membres non-publics de la classe Ecran.

62

Vous aimerez peut-être aussi