Vous êtes sur la page 1sur 54

Université Sid Mohammed Ben Abdellah

Ecole Nationale des Sciences Appliquées


Fès

Programmation Orientée Objet


C++

Pr. Nabil EL AKKAD

A. U: 2021/2022
Classes et objets
en C++

2
Points principaux
1. Structures en C++
2. Notion de classe
3. Affectation d’objets
4. Notions de constructeur et de destructeur
– Constructeur, initialisation et destructeur
5. Membres données statiques
6. Exploitation d’une classe
7. Classes en général
8. Propriétés des fonctions membres
3
Structures en C++ : rappel
Structures simples
• Une structure contient une ou plusieurs variables groupées sous le
même nom pour être traitées comme une seule entité.

• Contrairement aux variables stockées dans un tableau, les


variables d’une structure peuvent être de types différents.

• Une structure peut contenir tous les types de données C/C++, y


compris les tableaux et les autres structures.

• Chaque variable d’une structure est appelée membre de cette


structure.
4
Définition et déclaration des structures
On peut définir une structure point contenant les variables x et y de
cette façon :
struct point{
int x;
int y;
};

Le mot clé struct identifie le début de la structure et informe le


compilateur que point est de type structure.

Il y a deux façons de déclarer les structures :


struct point{
struct point{ int x;
int x; int y;
int y; };
} p1, p2; /* instructions ... */
struct point p1, p2;
5
Déclaration d'une structure comportant des
fonctions membres
Supposons qu’on souhaite associer à la structure point précédente trois
fonctions :
– initialise pour attribuer des valeurs aux "coordonnées" d'un point ;
– deplace pour modifier les coordonnées d'un point ;
– affiche pour afficher un point : ici, pour simplifier on affiche les
coordonnées du point.
/* ------------ Déclaration du type point ------------- */
struct point
{ /* déclaration "classique" des données */
int x ;
int y ;
/* déclaration des fonctions membre (méthodes) */
void initialise (int, int) ;
void deplace (int, int) ;
void affiche () ;
}; 6
Définition des fonctions membres
void point::initialise (int abs, int ord)
{ x = abs ;
y = ord ;
}
Dans l'en-tête, le nom de la fonction est : point::initialise
• Le symbole :: correspond à ce que l'on nomme l'opérateur de
"résolution de portée", faisant le lien entre la déclaration et la
définition de la fonction membre.. Ici, il signifie que l'identificateur
initialise concerné est celui défini dans point.
• En l'absence de ce "préfixe" (point::), nous définirions
effectivement une fonction nommée initialise, mais celle-ci ne
serait plus associée à point ; il s'agit d'une fonction "ordinaire"
nommée initialise, et non plus de la fonction membre initialise de la
structure point.
7
Définition des fonctions membres

#include <iostream>
using namespace std ;
void point :: initialise (int abs, int ord){
x = abs ; y = ord ;
}
void point :: deplace (int dx, int dy){
x += dx ; y += dy ;
}
void point :: affiche (){
cout << "Je suis en " << x << " " << y << "\n" ;
}

8
Utilisation d'une structure comportant des
fonctions membres
• On peut déclarer autant de structures de ce type que nous le souhaitons.
Par exemple :
point a, b ;
Déclare deux structures nommées a et b, chacune possédant des
membres x et y et disposant des trois méthodes initialise, deplace et
affiche.
– a.x = 5 ;
– a.initialise (5,2) ;
• a.x = 5 ; a.y = 2 ;
• Puisqu'il n’y a pas d'encapsulation des données, cette démarche est
purement artificielle. Alors que d'un point de vue conceptuel, elle permet
de mieux envisager la programmation, ainsi de préparer à la notion de
classe.
• En P.O.O., on dit également que a.initialise (5, 2) permet l'envoi du
message (informations 5 et 2) à l'objet a.
9
Exemple complet
#include <iostream>
using namespace std ;
/* ------------ Déclaration du type point ------------- */
struct point{ /* déclaration "classique" des données */
int x , y ;
/* déclaration des fonctions membres (méthodes) */
void initialise (int, int) ;
void deplace (int, int) ;
void affiche () ;
};
/* ----- Définition des fonctions membres du type point ---- */
void point::initialise (int abs, int ord) { x = abs ; y = ord ; }
void point::deplace (int dx, int dy) { x += dx ; y += dy ; }
void point::affiche () { cout << "Je suis en " << x << " " << y << "\n" ; }
main()
{ point a, b ;
a.initialise (5, 2) ; a.affiche () ; Je suis en 5 2
a.deplace (-2, 4) ; a.affiche () ; Je suis en 3 6
b.initialise (1,-1) ; b.affiche () ; Je suis en 1 -1
} 10
Exemple complet (suite)
• Une fonction membre ne peut pas être appelée comme une fonction
ordinaire. Ex. initialise (3,1)//erreur
Il faut avoir un point : point p; p.initialise(3,1);
• Dans la déclaration d'une structure, il est permis (mais généralement peu
conseillé) d'introduire les données et les fonctions dans un ordre quelconque
(on a systématiquement placé les données avant les fonctions).
• Dans notre exemple de programme complet, on a introduit :
– La déclaration du type point,
– La définition des fonctions membres,
– La fonction (main) utilisant le type point.
• Mais, bien entendu, il serait possible de compiler séparément le type point;
c’est d’ailleurs ainsi que l’on pourra "réutiliser" ce composant. 11
Notion de classe
• La notion de classe en C++ est une extension de la notion de structure du
C avec les concepts fondamentaux suivants :
– Couplage des données et des fonctions (appelées méthodes ou
fonctions membres);
– Encapsulation des données, statut privé:
Ces données privées ne peuvent être manipulées que par les méthodes de
la classe.

• La déclaration d'une classe est voisine de celle d'une structure, il suffit de :

– Remplacer le mot clé struct par le mot clé class,

– Préciser quels sont les membres publics (fonctions ou données) et les


membres privés en utilisant les mots clés public et private.
12
Notion de classe (suite)
• Classe :
– Regroupement de données (attributs ou champs) et de méthodes
(fonctions membres);
– Extension des structures (struct) avec différents niveaux de visibilité
(protected, private et public).
• Objet : instance de classe
– Attributs et méthodes communes à tous les objets d’une classe;
– Valeurs des attributs propres à chaque objet.
• Encapsulation
– En programmation orientée-objet pure : l’encapsulation des données:
accès unique aux données à travers les méthodes;
– Caractérisation d’un objet par les spécifications de ses méthodes:
interface;
– Indépendance vis à vis de l’implémentation.
13
Notion de classe (suite)

Objet = Données + Méthodes (Fonctions Membres)

Résistance

Fonction 1 Fonction 2 SetValueR SetValueP

Fonction Fonction GetRmin R P GetValueR


6
DONNEES 3

Fonction 5 Fonction 4 GetRmax GetValueP


Notion de classe (suite)

Accesseurs et Modificateurs
• Les Accesseurs

– Catégorie de fonctions membres qui permettent l’accès et


l’utilisation des informations privées contenues dans l’objet.

• Les Modificateurs

– Permettent de modifier l’état des données internes (publiques ou


privées) de l’objet.

15
Notion de classe (suite)
Quelques règles de programmation
1. Définir les classes, inclure les librairies etc. dans un fichier d’extension .h
 La classe est définie dans un fichier d ’extension .h ou .hxx
Exemple: point.h
2. Définir le corps des méthodes (fonctions membres), la fonction main etc. dans un
fichier d’extension .cpp, cxx, .C, .cc, (incluant le fichier .h)
 Les fonctions sont rattachées à la classe par l ’opérateur de portée ::
Exemple:
void point::initialise( int a ,int b)
3. Compiler régulièrement
 Penser à utiliser les commentaires et les coûts.
16
Notion de classe (suite)
Exemple d’une classe
#include <iostream>
using namespace std ;
/* ------------ Déclaration de la classe point -------------point.h */
class point
{ /* déclaration des membres privés */
private : /* facultatif */
int x ;
int y ;
/* déclaration des membres publics */
public :
void initialise (int, int) ;
void deplace (int, int) ;
void affiche () ;
};
17
Notion de classe (suite)
Exemple d’une classe (suite)
/* ----- Définition des fonctions membres de la classe point ---- point.cpp*/
void point::initialise (int abs, int ord) {
x = abs ; y = ord ;
}
void point::deplace (int dx, int dy) {
x = x + dx ; y = y + dy ;
}
void point::affiche () {
cout << "Je suis en " << x << " " << y << "\n" ;
}
/* -------- Utilisation de la classe point -------- */
main() {
point a, b ;
a.initialise (5, 2) ; a.affiche () ;
a.deplace (-2, 4) ; a.affiche () ;
b.initialise (1,-1) ; b.affiche () ;
18
}
Notion de classe (suite)
• Dans le jargon de la P.O.O., on dit que a et b sont des instances de la classe point,
ou encore que ce sont des objets de type point ; c’est généralement ce dernier terme
que l’on va utiliser.
• Dans notre exemple, tous les membres données de point sont privés, ce qui
correspond à une encapsulation complète des données. Ainsi, une tentative
d'utilisation directe (ici au sein de la fonction main) du membre a :
a.x = 5; //erreur de compilation
• Bien entendu, cette instruction serait acceptée si l’on avait fait de x un membre
public).
• En général, on cherchera à respecter le principe d'encapsulation des données, et donc
à prévoir des fonctions membres appropriées pour y accéder.
• Dans notre exemple, toutes les fonctions membres étaient publiques. Il est tout à fait
possible d'en rendre certaines privées. Dans ce cas, de telles fonctions ne seront
plus accessibles de l’"extérieur" de la classe. Elles ne pourront être appelées que par
d'autres fonctions membres.
19
Notion de classe (suite)

• Les mots clés public et private peuvent apparaître à plusieurs reprises


dans la définition d'une classe, comme dans cet exemple : class X
{ private :
• Si aucun de ces deux mots n'apparaît au début de la définition, ...
tout se passe comme si private y avait été placé. public :
...
• Si aucun de ces deux mots n'apparaît dans la définition d'une classe, private :
...
tous ses membres seront privés, donc inaccessibles. Cela sera rarement };
utile.
• Si l'on rend public tous les membres d'une classe, on obtient
l'équivalent d'une structure.
Ainsi, ces deux déclarations définissent le même type point :
class point
{
struct point public :
{ int x ; int y ;
int y ; int x ;
void initialise (...) ; void initialise (...) ;
.... ....
}; }; 20
Notion de classe (suite)

Il existe un troisième mot, protected (protégé), qui s'utilise de la même


manière que les deux autres ; il sert à définir un statut intermédiaire entre
public et privé, lequel n'intervient que dans le cas de classes dérivées.
(Chapitre héritage).

21
Affectation d’objet

struct point{ class point{


int x , y ; int x ;
public :
}; int y ;
struct point a, b ; ....
On peut tout à fait écrire: a = b; };
Cette instruction recopie point a, b ;
l'ensemble des valeurs des L'instruction : b = a ;
champs de b dans ceux de a. provoquera la recopie des valeurs des membres
Elle joue le même rôle de: x et y de a dans les membres correspondants de b.
a.x = b.x ; Contrairement à ce qui a été dit pour les
structures, il n'est plus possible ici de remplacer
a.y = b.y ; cette instruction par :
b.x = a.x ;
que ceux-ci soient publics ou b.y = a.y ;
non. En effet, la deuxième affectation est légale,
puisqu’ici «y» est public, alors que la première
ne l'est pas, car «x» est privé. 22
Constructeurs et destructeur

• Il est donc nécessaire de faire appel à une fonction membre pour attribuer
des valeurs aux données d'un objet. C'est ce que nous avons fait pour notre
type point avec la fonction initialise.

• Les objets suivent les règles habituelles concernant leur initialisation par
défaut :

• Un objet doit effectuer un certain nombre d’opérations nécessaires à son


bon fonctionnement, par exemple : allocation dynamique de mémoire,
vérification d’existence de fichier ou ouverture, connexion à un site
Web...

• L'absence de procédure d’initialisation peut alors devenir catastrophique.


23
Constructeurs et destructeur (suite)
 Constructeurs
• Le constructeur est une solution très performante pour traiter ces problèmes;
– Un constructeur est une fonction qui est appelé à la création de chaque
nouvelle instance de la classe;
– Rôle (principalement) : alloue la mémoire et initialise les attributs;
– Même nom que le nom de la classe;
– Définition de l'initialisation d'une instance de la classe;
– Appelé implicitement à toute création d'instance de la classe;
– Méthode non typée, pouvant être surchargée;
– Il est défini avec une visibilité public;
– Le constructeur par défaut:
• Ne contient aucun argument:
• Automatiquement généré si aucun constructeur n’est défini;
NB: À partir du moment où une classe possède un constructeur, il n’est plus
possible de créer un objet sans fournir les arguments requis par son constructeur
(sauf si ce dernier ne possède aucun argument !). 24
Exemple de constructeur

Personne.h Personne.cpp
class Personne{
public : Personne:: Personne(){
// Instructions du constructeur par défaut
Personne(); identifiant = 1;
Personne(int id); }
private : Personne:: Personne(int id)
int identifiant; {
}; identifiant = id;
}

main.cpp
int main(int argc, char argv){
Personne p1; //Appel de Personne()
Personne p2(2); //Appel de Personne(int)
Personne *pp3, *pp4;
pp3 = new Personne(); //Appel de Personne()
pp4 = new Personne(4); //Appel de Personne(int)
return 0;
} 25
Constructeur par recopie

• Quand on fait une copie de l’objet, des traitements particuliers sont


souvent à réaliser.
• On utilise alors le constructeur par recopie

Personne.h Personne.cpp
class Personne Code : Constructeur par recopie
{
public : Personne::Personne(const Personne& personne)
... {
Personne(const Personne&); identifiant = personne. identifiant;
... }
};

26
Questions
• Soit la définition de la classe T
class T{
public :
T();
T( int );
T(double);
T(const T&);
};
Quel constructeur est appelé ?
– T t1; //T :: T();
– T t2(12); //T :: T( int );
– T t3(t1); //T :: T(const T&);
– T t4() ; //Ce n'est pas une instruction c' est un prototype
27
Destructeur
• Appelé à chaque fois qu'une instance de la classe est détruite
(automatiquement);
– Rôle : libérer la mémoire;
– De même nom que la classe mais précédé d'un tilde (~);
– Définition de la désinitialisation d'une instance de la classe;
– Appelé implicitement à toute disparition d'instance de la classe:
fermeture d'accolade }
– Méthode non typée et sans paramètre;
– Ne pouvant pas être surchargé;
– Par défaut un destructeur vide est implémenté;
– Il est défini avec une visibilité public;
– delete fait appel au destructeur alors que free ne le fait pas
• Peut être appelé explicitement: delete a; delete[] a;
• a.~MaClasse(); //Pas recommandé…
28
Exemple de destructeur
Personne.cpp
Personne.h Personne:: Personne(int id){
class Personne{ identifiant = id;
Allocationdyna = new int();
private : }
int Personne:: ~Personne(){
*allocationdyna; delete allocationdyna ;
int identifiant; }…
public :
Personne(int id); main.cpp
Personne(); int main(int argc, char argv)
~Personne(); {
}; Personne p1, *pp3; //Appel de Personne()
pp3 = new Personne();
if(p1){
Personne p2;
} //Appel de ~Personne()
delete pp3; //Appel de ~Personne()
} //Appel de ~ Personne() 29
Exemple de destructeur (suite)

class Tableau {
int *t; int main()
public: { Tableau T;
Tableau(int s = 10) { // …
//constructeur
t = new int[s]; return 0;
} } /*Destructeur ~Tableau()
appelé automatiquement
~Tableau() { // destructeur en fin de portée*/
delete [] t;
}
};

30
Exemple de destructeur (suite)
// Exemple de constructeur effectuant une allocation repris de [Delannoy]
class TableauDEntiers {
int nbElements;
int * pointeurSurTableau;
public:
TableauDEntiers(int, int); // Constructeur
~ TableauDEntiers(); // Destructeur
…}
// Constructeur allouant dynamiquement de la mémoire pour nb entiers
TableauDEntiers::TableauDEntiers (int nb, int max) {
pointeurSurTableau = new int [nbElements=nb] ;
for (int i=0; i<nb; i++) // nb entiers tirés au hasard
pointeurSurTableau[i]= double(rand())/ RAND_MAX*max;
} // rand() fournit un entier entre 0 et RAND_MAX (cte varie suivant les compilat.
<32767)
TableauDEntiers::~TableauDEntiers () {
delete [] pointeurSurTableau ; // désallocation de la mémoire
31
}
#include <iostream>
Exemple : classe point
using namespace std ;
/* ------------ Déclaration de la classe point ------------- */
class point{
/* déclaration des membres privés */
int x, y ;
/* déclaration des membres publics */
public :
point (int, int) ; // constructeur
~point () ; // destructeur
void deplace (int, int) ;
void affiche () ;
};
/* ----- Définition des fonctions membre de la classe point ---- */
point::point (int abs, int ord) {x = abs ; y = ord ;}
point::~point () {cout << " Destructeur …\n" ;}
void point::deplace (int dx, int dy) { x = x + dx ; y = y + dy ;}
void point::affiche () { cout << "Je suis en " << x << " " << y << "\n" ;}
/* -------- Utilisation de la classe point -------- */
main() {
point a(5,2) ; a.affiche () ; Je suis en 5 2
a.deplace (-2, 4) ; a.affiche () ; Je suis en 3 6
point b(1,-1) ; b.affiche () ; Je suis en 1 -1
32
} //appel des destructeurs Destructeur …
Appel des constructeurs et des destructeurs
class point{
/* déclaration des membres privés */
int x, y ;
/* déclaration des membres publics */
public :
point (int, int) ; // constructeur1
~point () ; // destructeur
void deplace (int, int) ;
void affiche () ;

};

main() {
point a ; // Erreur: le constructeur attend deux arguments
point b (3) ; // Erreur (même raison)
}

33
Appel des constructeurs et des destructeurs (suite)
class point{
/* déclaration des membres privés */
int x, y ;
/* déclaration des membres publics */
public :
point (int, int) ; // constructeur1
point () ; // constructeur2
~point () ; // destructeur
void deplace (int, int) ;
void affiche () ;
};

main() {
point a ; // ou point a() OK :
point b(1, 7) ; // OK
point b (3) ; // Erreur : le constructeur attend deux arguments
} //appel des destructeurs
RQ: Une déclaration telle que :
point a ; // attention, point a () serait une déclaration d’une fonction a
point a : est acceptable dans deux situations différentes :
– Il n'existe pas de constructeurs de point,
34
– Il existe un constructeur de point sans argument.
Appel des constructeurs et des destructeurs (suite)

• Lorsqu’il y a plusieurs constructeurs, l’opérateur new choisit le


bon constructeur grâce au nombre et/ou à la nature des
arguments point *p=new point(…)
• S’il n’existe pas de constructeur ou s’il existe un constructeur
sans argument, new point; ou new point (); sont acceptés
• Si tous les constructeurs possèdent au moins un argument, new
point; et new point (); sont rejetés

35
Objets dynamiques
structures :

struct S1
{ int x ; Déclaration :
double y ; En C : struct S1 * adr ;
int t [5] ; En C++ : S1 * adr ;
};
•Allocation dynamique
L'instruction : adr = new S1; réalise une allocation dynamique
d'espace mémoire pour un élément de type S1 et affecte son
adresse au pointeur adr.
•Accès aux différents champs:
adr -> y; // ou (*adr).y
•Libération de mémoire :
delete adr ; 36
Objets dynamiques (suite)
class point{
int x, y ; /* déclaration des membres
privés */
public : /* déclaration des membres publics */ •Déclaration:
point (int, int) ; // constructeur1 point * p;
~point () ; // destructeur
void deplace (int, int) ;
void affiche () ;
};
•Allocation dynamique
L'instruction : p= new point(1,4) ;
crée dynamiquement un emplacement de type point (qui contiendra donc
ici la place pour deux entiers) et affecte son adresse à p
•Accès aux fonctions membres de l’objet pointé par p :
p-> affiche () ; //(* p).affiche () ;
p-> x; // si x public
•Libération de mémoire (suppression de l’objet ):
delete p; 37
Utilité des opérateurs new et delete

• Après l'allocation dynamique de l'emplacement mémoire requis, l'opérateur


new appellera un constructeur de l’objet ; ce constructeur sera déterminé par
la nature des arguments.
• L'opérateur new permet de faire:
– Une allocation dynamique de l'emplacement mémoire requis;
– Un appel au constructeur adéquat de l’objet ;
new point (2, 5) ; // a = point (2, 5) ;
new point ; // ou new point ()
• Avant la libération de l'emplacement mémoire correspondant, l'opérateur
delete appellera le destructeur.

38
Exemple
#include <iostream> main() {
using namespace std ; void fct (point *) ; // prototype fonction fct
point * p;
class point{
cout << "** Debut main \n" ;
int x, y ; p= new point (3,7) ; //création dynam. d'un objet
public : fct (p) ;
point (int abs, int ord) { // constructeur cout << "** Fin main \n" ;
x=abs ; y=ord ; }
void fct (point * adp) {
cout << "++ Appel Constructeur \n" ;
cout << "** Debut fct \n" ;
} delete adp ; // destruction de cet objet
~point () // destructeur (en fait, inutile ici) cout << "** Fin fct \n" ;
{ cout << "-- Appel Destructeur \n" ; }
}
}; ** Debut main
++ Appel Constructeur
** Debut fct
- - Appel Destructeur
** Fin fct
39
** Fin main
Constructeur de recopie
Mise en évidence du problème

Schéma de l’opération effectuée lors de l’appel de la


méthode add, transmission de b par valeur.

40
Constructeur de recopie (suite)

schéma de l’opération effectuée lors de l’appel de


la méthode add transmission de b par valeur

• Copie de size (int)


• Copie p (pointeur)

b.p et v.p pointent sur


le même tableau

41
Constructeur de recopie (suite)

A la fin de l'exécution de la fonction add , le destructeur ~vector


est appelé pour v, ce qui libère l'emplacement pointé par p;

42
Constructeur de recopie (suite)

Cette tentative constitue une erreur


d'exécution dont les conséquences varient avec
l’implémentation.

43
Constructeur de recopie (suite)

On définit un construteur par recopie (appelé automatiquement lors de la copie d’un


objet) de la forme :
vector(const vector&); ou bien vector(vector &);

En général, un constructeur par recopie n’a pas de raison de modifier l’objet passé en
argument. De plus, une fonction prévue pour un objet constant peut toujours s’utiliser
pour un objet non constant (réciproquement fausse)
vector(const vector&);
44
Constructeur de recopie (suite)

La transmission par valeur d’un argument ou d’une


valeur de retour d’une fonction met en œuvre une
recopie.
Elle est réalisée soit:
• Par le constructeur de recopie par défaut (si
aucun n’a été défini);
• Par le constructeur de recopie surdéfini dans la
classe.
Lorsqu’un objet comporte des données dynamiques,
il est indispensable de définir un constructeur par
recopie.

45
Quelques règles
• Un constructeur peut comporter un nombre quelconque d’arguments,
éventuellement aucun.

• Par définition, un constructeur (destructeur) ne renvoie pas de valeur ; aucun


type ne peut figurer devant son nom (la présence de void est une erreur).

• En théorie, les constructeurs et les destructeurs peuvent être publics ou privés. En


pratique, à moins d’avoir de bonnes raisons de faire le contraire, il vaut mieux les
rendre publics.

• On notera que, si un destructeur est privé, il ne pourra plus être appelé


directement, ce qui n’est généralement pas grave, dans la mesure où cela est
rarement utile.

• En revanche, la privatisation d’un constructeur a de lourdes conséquences


puisqu’il ne sera plus utilisable, sauf par des fonctions membres de la classe elle-
même.

46
Objets automatiques et statiques
• Durée de vie
– Le moment où ils sont créés et celui où ils sont détruits,
– Les règles s'appliquant aux variables ordinaires se transposent tout naturellement aux
objets.
• Les objets automatiques sont créés par une déclaration :
• Dans une fonction : l’objet est créé lors de la rencontre de sa déclaration (celle ci
peut être précédée, au sein de ce bloc, des autres instructions), et détruit à la fin de
l'exécution de la fonction.
• Dans un bloc : l’objet est aussi créé lors de la rencontre de sa déclaration, et
détruit lors de la sortie du bloc.
• Les objets statiques sont ceux créés par une déclaration située :
– En dehors de toute fonction,
– Dans une fonction, mais assortie du qualificatif static.
Les objets statiques sont créés avant le début de l'exécution de la fonction main et détruits
après la fin de son exécution.
• Les objets temporaires
Appel direct au constructeur d’une classe:
point (1,2); //=> objets temporaires
point a(0,0); a = point (1,2); // copier l’objet temporaire dans a
47
Données membres statiques

- Applicables aux attributs et aux méthodes;


- Définition de propriété indépendante de tout objet de la classe 
propriété de la classe .

Les membres statiques sont des variables/ fonctions partagées par toutes
les instances de la classe (données globales partagées ).
• Présents une seule fois en mémoire.
• La visibilité et les droits d'accès sont conservés.

On parle alors de champs de classe ou de champs statiques.


Appel à une méthode statique se fait de cette manière: MaClasse::
48
MaMethode ()
Champs de classe

Considérons la définition de la classe suivante :


class A
{ int n ;
float y ;
};
Chaque objet de type A possède ses propres champs n et y. Par exemple, avec
cette déclaration :
A a1, a2;

On aboutit à une situation qu’on peut schématiser comme suit:

49
Champs de classe (suite)
C++ permet de définir ce qu’on nomme des champs de classe (ou statiques) qui
n’existent qu’en un seul exemplaire, quel que soit le nombre d’objets de la classe.
class B
{ static int n ;
float x ;
}
B a ,b;
On aboutit à cette situation :

Les notations a.n et b.n désignent donc le même champ.


On peut dire que les membres données statiques sont des sortes de variables
globales dont la portée est limitée à la classe.
RQ: ces notations (a.n, b.n) ne seront utilisables que pour un champ public. Pour
des champs statiques privés, l’accès pourra se faire par le biais de méthodes.

50
Exemple 1
main() {
#include <iostream> void fct () ;
using namespace std ; Aa;
class A{ fct () ;
static int cmp; // compteur du nombre d'objets créés Ab;
public : }
A() ; void fct (){
~A() ; A u, v ;
}; }
int A:: cmp = 0 ; // initialisation du membre statique cmp
A::A() // constructeur
{ cout << "++ construction : il y a maintenant " << ++ cmp << " objets\n" ;
}
A::~A() // destructeur
{ cout << "-- destruction : il reste maintenant " << -- cmp << " objets\n" ;
} ++ construction : il y a maintenant 1 objets
++ construction : il y a maintenant 2 objets
++ construction : il y a maintenant 3 objets
-- destruction : il reste maintenant 2 objets
-- destruction : il reste maintenant 1 objets
++ construction : il y a maintenant 2 objets
-- destruction : il reste maintenant 1 objets 51
-- destruction : il reste maintenant 0 objets
Exemple 2
TestStatic.h
class TestStatic { // initialisation de membre statique
static int NbObjets; // Attribut statique int TestStatic::NbObjets=0;
public: int main () {
// constructeur cout << "Nombre d'objets de la classe :"
<< TestStatic ::GetNbObjets() << endl;
TestStatic() {NbObjets++;};
// Affichage du membre statique TestStatic a; a.AfficherNbObjets();
void AfficherNbObjets () { TestStatic b, c;
cout << "Le nombre d'objets crées est : " b.AfficherNbObjets(); c.AfficherNbObjets();
<< NbObjets << endl; TestStatic d;
}; d.AfficherNbObjets(); a.AfficherNbObjets();
}
static int GetNbObjets() {return NbObjets;};
};
Nombre d'objets de la classe : 0
Le nombre d'objets crées est : 1
Le nombre d'objets crées est : 3
Le nombre d'objets crées est : 3
Le nombre d'objets crées est : 4
Le nombre d'objets crées est : 4 52
Exploitation d’une classe
• La classe est considérée comme un composant logiciel
• Jusqu’ici, nous avions regroupé au sein d’un même programme trois sortes
d’instructions destinées à :
– La déclaration de la classe,(point.h)
– La définition de la classe, (point.cpp)
– L’utilisation de la classe. (main.cpp)
• En pratique, on aura souvent intérêt à découpler la classe de son
utilisation.
– C’est tout naturellement ce qui se produira avec une classe d’intérêt
général utilisée comme un composant séparé des différentes
applications.

53
Exercice

• Ecrivez une classe vecteur comportant :


– Comme membres données privés : trois composantes de type double: x, y et z
– Comme fonctions membres publiques :
• Initialise pour attribuer des valeurs aux composantes,
• Produit pour multiplier les composantes par une valeur fournie en
argument
• Affiche pour afficher les composantes du vecteur.
• Ecrivez une classe vecteur analogue à la précédente, dans laquelle la fonction
initialise est remplacée par un constructeur.
• Ajouter 2 autres constructeurs et un destructeur
• Tester cette classe en créant 3 objets(a, b et c) et en appelant les deux méthodes :
produit et affiche.
54

Vous aimerez peut-être aussi