Kamel Hamrouni
Abir Gallas
Introduction
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.
4
Définition d’une classe (2)
Exemple
class Avion
{ private : // membres privées
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 :
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)
8
Recommandation de style
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.
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
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
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
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 ) ; }
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;}
22
Fonctions constantes
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 ...).
28
Constructeurs (2)
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;
};
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()
{ // ... }
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