Vous êtes sur la page 1sur 36

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

É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

Vous aimerez peut-être aussi