You are on page 1of 195

Le langage C++ & POO

M. AMEUR
Plan

Conception Objet

Introduction au C++

Classes

Hritage

Polymorphisme

Gestion des exceptions

Bibliothque STL ( Standard Template Library)

et ++...
Bibliographie

Le Langage C++ (The C++ Programming Language), de


Bjarne Stroustrup, Addisson-Wesley dernire dition
2003
How to program C and introducing C++ and Java, de
H.M. Deitel et P.J. Deitel, Prentice Hall, 2001 dernire
dition C++ How To Program de fvrier 2005
Programmer en langage C++ , 6me dition de Claude
Delannoy, Eyrolles, 2004
Exercices en langage C++, de Claude Delannoy, Eyrolles,
1999
Documents en ligne

Thinking in C++ de Bruce Eckel, 2003


http://mindview.net/Books/TICPP/ThinkingInCPP2e.html
http://www.librecours.org
http://www.freetechbooks.com/
http://www.cplusplus.com/
Http://www.siteduzero.com

Google est votre ami


Rappels sur le langage C
C'est un langage de haut niveau
Les programmes en C fonctionnent avec des fonctions
(procdurale).
La principale est main().
Types dinstruction en C
Dclarations des variables

Assignations

Fonctions

Contrle
Les variables
Pour dclarer une variable, on fait prcder son nom par son type.
Il existe 6 types de variables :
char caractre cod sur 1 octet
short entier cod sur 1 octet
int entier cod sur 4 octets
long entier cod sur 8 octets
float rel cod sur 4 octets
double rel cod sur 8 octets
On peut faire prcder chaque type par le prfixe unsigned, ce qui force les variables prendre
des valeurs uniquement positives.
Affichage sur l'cran
Fonction printf() de la bibliothque stdio.h
Saisie au clavier
La fonction getch() bibliothque conio.h
Saisie d'un caractre alphanumrique sans echo cran

La fonction scanf() bibliothque stdio.h


Saisie de n'importe quel type de variable avec formatage.
Condition
Les deux conditions principales sont if et switch :
if(test)
{
/*code excuter si le test est vrai*/
}

else
{
/* code excuter si le test est faux*/
}

switch(variable)
{
case valeur1:
/* bloc 1*/
break;
case valeur2:
/* bloc 2*/
break;
default:
/* bloc_par_dfaut*/
break;
}
Les boucles
Il existe deux types de boucle:
La boucle for permet de runir la dclaration, la condition et
l'incrmentation.
int i;

for(i = 0; i < 10; i++)


{
/* bloc rpter */
}

La boucle while
int i = 0;
do {
while(i < 10)
{ /*instructions ... */
/* bloc rpter */
i++;
} } while (expression)
Les fonctions
Une fonction permet de renvoyer un rsultat en fonction des donnes passes
en paramtres. Pour dclarer une fonction, a prend la forme :
int carre(int nombre)
{
return nombre * nombre;
}

La dclaration doit tre faite avant l'appel de la fonction qui se fait comme ceci :
int retour = carre(2);

La variable retour contient 4.


Les pointeurs
Un pointeur contient ladresse dune autre
variable.
Dclaration:
float *nombre; // rserve un emplacement pour stocker une @
mmoire

Utilisation:
nombre = &nb2 ; //Contenu de nombre = adresse de nb2

*nombre = 30.5 ; //Mme effet que nb2 = 30.5.


Pointeurs et Tableaux
int tab[10] = { 1,2,3,4,5,6,7,8,9,10}; // dclaration dun
tableau de dimension 10.
tab dsigne ladresse du premier lment du tableau
On peut lutiliser comme un pointeur pour parcourir le tableau:
printf(%d, *tab); // affiche 1 quivalent tab[0]
On peut dclarer un pointeur sur un tableau de la faon suivante
int *ptab; ptab=tab;
printf(%d, ptab[0]); // affiche 1 ; cest le mme tableau.
Arithmtique des pointeurs
Incrmentation/dcrmentation de pointeur :
L'incrmentation (ou la dcrmentation) de pointeur exprime le fait que l'on
veuille atteindre l'lment point suivant (ou prcdent).
Le rsultat est correct que si l'objet point est situ dans un mme tableau.
Ainsi avec la dfinition suivante :
int *ptr;
les instructions ptr++; ou ptr = ptr + 1; sont quivalentes.
Elles incrmentent la valeur du pointeur de la longueur du type de l'objet
point, permettant ainsi de dsigner le dbut de l'lment suivant.
Ces oprations sont impossibles avec des pointeurs sur un type void.
Arithmtique des pointeurs
Addition/soustraction de 2 pointeurs :
l'addition de 2 pointeurs n'a pas de sens et est donc sans signification.
la soustraction de 2 pointeurs (de mme type) situs dans un mme tableau,
retourne le nombre d'lments qui les sparent.
Exemple : int *pt1 = &tab[2] , *pt2 = &tab[6];
printf("%d\n", pt2 - pt1); /* affiche : 4 */

Comparaison de pointeurs :
Un pointeur ne pourra tre compar qu' un pointeur sur le mme
type (ou la constante NULL). Le rsultat de la comparaison
sera significatif et portable que si les pointeurs pointent sur le
mme objet.
Arithmtique des pointeurs
Exemples:
int *P;

P = tab+9; /* dernier lment -> lgal */

P = tab+10; /* dernier lment + 1 -> lgal */

P = tab+11; /* dernier lment + 2 -> illgal */

P = tab-1; /* premier lment - 1 -> illgal */


Tableaux 2d et les pointeurs
Lien entre un tableau 2 dimension et les pointeurs
Un tableau 2d est un tableau de tableaux 1d
On peut dire que le nom dun tableau 2d est ladresse dun
tableau 1d contenant les adresses de tableaux 1d.
Pointeurs de pointeurs.
Exemple:
Int tab[6][7];
Int **p; // dclaration dun pointeur de pointeurs
p=tab; // initialisation du pointeur de pointeurs
Allocation de mmoire
Int * t;
t= (int*) malloc ( taille* sizeof(int));
Allocation pour un tableau 2d nxm par exemple:
Int **tab, i;
tab= (int**) malloc ( n* sizeof(int*));
for(i=0; i<n ; i++)
tab[i]=(int*) malloc ( m* sizeof(int));
Dsallocation de mmoire
for(i=0;i<n; i++)
free( tab[i]);
free(tab);
Conception Objet

Critres de ''qualit'' d'un logiciel


Lexactitude
La robustesse
Lextensibilit
Lefficience : performances en terme de vitesse et
consommation de mmoire,
La portabilit : support d'une autre implmentation
La rutilisabilit
La modularit
Conception Objet
Programmation structure
La construction d'un logiciel se base fondamentalement sur
l'quation de WIRTH:

Algorithme + Structure de donnes = Programme

La conception d'un programme structur peut tre base soit:


Sur le traitement (approche traditionnelle)
Sur les donnes
Concepts fondamentaux des objets

Encapsulation des donnes


consiste faire faire une distinction entre l'interface de l'objet et son
implmentation.

Implmentation
Donnes Mthodes * Interface: dcrit ce que fait
l'objet

Pri
Priv Priv
v * Implmentation: dfinit
comment raliser l'interface.
Public Public Public

Interface
Concepts fondamentaux des objets

Encapsulation des donnes (suite)


le principe de l'encapsulation est qu'on ne peut agir que sur les
proprits publiques d'un objet.
Exemple de la ncessit de protger les donnes:
supposons qu'on a une classe Temprature;
class Temperature:
attributs public: int TC; // temprature en Celsius
int TK; // temprature en Kelvin
supposons qu'on a une temprature TC=35 et TK=108 ;et que dans le code on a modifi
TC=40 (TK est toujours gale 108) il n' y a plus de cohrence des donnes.
Le bon code serait:
class Temperature:
attributs private: int TC; mthode public: set_TC(t){ TC=t;
int TK; TK=t+273;}
Concepts fondamentaux des objets

Communication par messages


les objets communiquent entre eux par des messages ( un objet
demande un service un autre objet) pour rsoudre un problme
final .
Objet 1 Message
Association simple
Agrgation
Composition Objet 3
...
Objet 2

Remarque: Les relations d'association, d'agrgation et de composition s'expriment


en insrant des variables membres dans une dfinition de classe.
Concepts fondamentaux des objets

Identit et classification
Consiste regrouper les objets ayant le mme comportement pour
former un mme ensemble , appel: classe ( cd un nouveau type).
Un objet d'une classe s'appellera une instance de cette classe.
En C++ on dclare une classe par :
class Maclasse { ..........};

Exemple: class Livre { Une instance de cette classe par exemple:


Le livre:
char* titre; Titre=''Lon l'africain''
char* auteur; Auteur=''Amine Malouf''
void lire(){....};
};
Concepts fondamentaux des objets

Hritage
Consiste dfinir une nouvelle classe partir d'une classe existante
laquelle on va ajouter de nouvelles proprits ( attributs et/ou
mthodes).
Concepts fondamentaux des objets

Polymorphisme
possibilit divers objets de classes drives d'une mme classe de
rpondre au mme message chacun sa faon. i.e un mme nom
peut dsigner des proprits de classes diffrentes.
Exemple: on peut invoquer la mthode ouvrir() quelque soit le type de
la porte automatique ou classique.

Gnricit
consiste dfinir des classes paramtres. Une classe gnrique n'est
pas directement utilisable, mais permet de crer des classes drives
qui peuvent tre manipules.

Modularisation
les modules sont construits autour des classes.
Concepts fondamentaux des objets

La programmation base sur les objets et leurs


concepts fondamentaux est dite la
Programmation Oriente Objets
(POO)

L'approche objet rpond bien aux critres de


qualits de production d'un logiciel.
Le Langage C++

Un peu d'histoire
C++ se base essentiellement sur 2 langages:
Simula 67 (1967) cre pour le traitement des problmes de
simulation, dont il hrite le concept objet ( un programme
autonome actif pouvant communiquer et se synchroniser
avec d'autres objets) .
Langage C (1972) aux Bell Labs.

Bjarne Stroustrup (Bell Labs), le concepteur du C++, dsirant ajouter


au C les classes de simula,cra le C++ aprs plusieurs version il
aboutit en 1983 une version stable.
Le Langage C++

C++ versus C
C++ dispose d'un certain nombre de spcificits par rapport C en
dehors de l'orient objet:
Les commentaires
L'emplacement libre des dclarations des variables
Les arguments par dfaut
La surcharge (surdfinition) des fonctions
Les oprateurs new et delete
Les fonctions en ligne ( inline)
Les rfrences
...
Le Langage C++

La fonction principale
la fonction main() est le point d'entre de tout programme C++. Elle peut
tre dfinie de 2 manires:
Pour les programmes sans paramtres: int main() {....}
Pour les programmes avec paramtres:
int main( int argc, char* argv[]){...}
o argc: le nombre de paramtres
et argv[]: tableau de paramtres
Le Langage C++

Les commentaires
Sur plusieurs lignes: /* .............comme en C....
...............*/
Sur une seule ligne: //.... spcifique C++......
Le Langage C++

Les E/S
Entres/sorties fournies travers la librairie < iostream>
cout << expr1 << << exprn
Instruction affichant expr1 puis expr2, etc.
cout : flot de sortie associ la sortie standard (stdout)
<< : oprateur binaire associatif gauche, de premire oprande
cout et de 2me lexpression afficher, et de rsultat le flot de sortie
<< : oprateur surcharg (ou sur-dfini) utilis aussi bien pour les chanes de caractres,
que les entiers, les rels etc.
cin >> var1 >> >> varn
Instruction affectant aux variables var1, var2, etc. les valeurs lues au clavier.
cin : flot dentre associe lentre standard (stdin)
>> : oprateur similaire <<
Le Langage C++

E/S (2)
Possibilit de modifier la faon dont les lments sont lus ou crits dans le flot :

#include <iostream.h>
#include <iomanip.h> // attention a bien inclure cette librairie
int main() {
int i=1234;
float p=12.3456;
cout << "|" << setw(8) << setfill('*')
<< hex << i << "|" << endl << "|"
<< setw(6) << setprecision(4)
<< p <<''|'' << endl;
}
Le Langage C++

Les types de base


Hritage des mcanismes de bases du C (pointeurs inclus)
Attention : typage fort en C++!!
Dclaration et initialisation de variables :
bool var_bool = true; // variable bolenne nouveu type en C++
int i = 0; // entier
long j = 123456789; // entier long
float f = 3.1; // rel
// rel double prcision
double pi = 3.141592653589793238462643;
char c=a; // caractre
Initialisation la mode objet :
int i(0) ;
Long l (123456789);
Le Langage C++

Type de base (2)


Le type dune donne dtermine :
La place mmoire (sizeof())
Les oprations lgales
Les bornes
Le Langage C++

Les constantes
Le qualificatif const peut tre utilis pour une expression
constante:
const type_var var=cte;

Une expression dclare avec const a une porte limite au


fichier source qui la contient.
Exemple:
const int N=5; // par convention une constante est crite en majuscule
int t[N]; // en C il fallait #define N 5
Le Langage C++

Les rfrences
une rfrence sur une variable est un identificateur qui joue le rle d'un alias (pseudo)
de cette variable.
Syntaxe: type &nom_ref = var;
exemple:
int n;
int &rn=n; // rn est une rfrence de n
n=10;
cout<< rn; //affiche 10

Une rfrence ne peut tre vide, elle doit toujours tre initialise lors de sa
dclaration, i.e : int &rn ; // erreur!

Il est possible de rfrencer des valeurs numriques, dans ce cas il faut les dclarer
comme constantes, i.e: int &rn=3; // erreur!
const int &rn=3; // OK

Les rfrences et les pointeurs sont lis.
Le Langage C++

Dclaration des fonctions



L'utilisation d'une fonction sans aucune dclaration ou dfinition au pralable
erreur la compilation.

Le prototype doit figurer dans tout fichier source qui utilise cette fonction et ne
contenant pas sa dfinition.

Une fonction en C++ doit spcifier son type de retour, void si elle ne retourne
rien.
fct(int, int); // erreur!
void fct(int, int); //OK


int fct(void); int fct();
Le Langage C++

Transmission des arguments


En C++ il y a 3 mthodes de passage des variables en paramtres une fonction:
Passage par valeur: la valeur de la variable en paramtre est copie dans une
variable temporaire. Les modifications opres sur les arguments dans la fonction
n'affectent pas la valeur de la variable passe en paramtre.
Passage par adresse: consiste passer l'adresse d'une variable en paramtre.
Toute modification du paramtre dans la fonction affecte directement la variable
passe en paramtre.
Passage par rfrence: le passage par adresse prsente certains inconvnients,
pour rsoudre ces inconvnients, C++ introduit le passage par rfrence.
En pratique, il est recommand ( pour des raisons de performances) de passer par
rfrence tous les paramtres dont la copie peut prendre beaucoup de temps.
Le Langage C++

Arguments par dfaut


C++ offre la possibilit de donner des valeurs par dfaut aux
paramtres d'une fonction ( exo TD).
Une fonction peut dfinir des valeurs par dfaut pour tous ses
paramtres ou seulement une partie.
Les valeurs par dfaut doivent tre mentionnes soit dans le
prototype de la fonction soit dans sa dfinition.
Les paramtres ayant une valeur par dfaut doivent tre placs
en dernier dans la liste des arguments.
Void fct ( int = 33 , int); //erreur!
Le Langage C++

Surcharge des fonctions


La surcharge (surdfinition) des fonctions consiste donner un mme nom
plusieurs fonctions.
int max(int a, int b); // fonction 1
int max( int a, int b, int c); // fonction 2
int max( int* tab, int taille); // fonction 3
Pour diffrencier entre deux fonctions qui portent le mme nom, le compilateur
regarde le type et le nombre des arguments effectifs: la liste des types des
arguments d'une fonction s'appelle la signature de la fonction.
La surcharge n'est acceptable que si toutes les fonctions ont des signatures
diffrentes, et n'a un sens que si les surdfinitions ont un mme but.
Il est galement possible de surcharger les oprateurs( voir les classes)
Le Langage C++

Les fonctions inline


Une fonction ''inline'' est une fonction dont les instructions sont
incorpores par le compilateur chaque appel.
Syntaxe: inline type fonct( arguments...) { }
Les fonctions ''inline'' permettent de gagner au niveau temps
d'excution, mais augmentent la taille des programmes en mmoire.

Contrairement aux macro dans C, les fonctions ''inline'' vitent les
effets de bord ( dans une macros l'argument peut tre valu
plusieurs fois avant l'excution de la macro).
Le Langage C++

Allocation dynamique
en C la manipulation dynamique de la mmoire se fait avec malloc et
free (<stdlib.h>). En C++, ces fonctions remplaces
avantageusement par les oprateurs unaire new et delete.
main()

int *pi = new int;

int *tab = new int[10];

if ((pi != NULL) && (tab != NULL))

...

delete pi;

delete [] tab;

}
Classes & objets

Dfinition d'une classe


La dclaration d'une classe consiste dcrire ses membres (membres
donnes et prototypes de ses fonctions membres) groups en
sections. Chaque section est tiquete par l'un des mots cls :
private, public, ou protected, qui prcisent le mode d'accs aux
membres contenus dans la section.
private: accs autoris seulement par les fonction membres
public: accs libre
protected: accs autoris seulement dans les fonctions membres de
la classe et de ses drives (voir hritage).
Pour dclarer une classe, on utilise le mot cl class.
Classes & objets

Exemple
class Point
{
private:
int x; Donnes membres ( ou attributs) privs
int y;
public:
void initialise(int,int);
void deplace(int,int); Mthodes public

void affiche();
} ;

Attention au point virgule aprs la dfinition d'une classe


Classes & objets

La mention d'accs par dfaut dans une classe est private:


class Point
{
int x;
// membres privs par dfaut
int y;
public: // membres publiques
};

La dfinition d'une classe consiste dfinir les prototypes


des fonctions membres. Pour les dfinir on utilise
l'oprateur de porte (::) :
type nom_class::fct(arguments) {}
Classes & objets
Au sein de la dfinition d'une fonction membre, les autres
membres (privs ou publiques) sont directement
accessibles (il n'est pas ncessaire de prciser le nom de
la classe):
void point::initialise(int abs, int ord)

x = abs;

y = ord;

}
Remarques:
Toutes les possibilits offertes par C++ pour les fonctions restent valables
pour les fonctions membres (surcharge, arguments par dfaut, ).
Toute fonction membre dfinie dans sa classe (dans la dclaration de la
classe) est considre par le compilateur comme une fonction inline. Le mot
cl inline n'est plus utilis.
Classes & objets

Utilisation d'une classe


Un objet (ou instance) nom_objet d'une classe, nomme nom_classe est
dclar comme une variable de type nom_classe :
nom_classe nom_objet;

On peut accder n'importe quel membre publique d'une classe en utilisant


l'oprateur (.) (point). Par exemple:

Point A;

A.initialise(10,12); // appel de la fct membre initailise de la classe 'Point'


//Cout<<'' l'abscisse du point A est'' <<A.x<<endl; //erreur car x est un attribut priv!!
A.affiche();
Classes & objets

Constructeur/Destructeur
C++ permet l'utilisation de fonctions membres dites constructeurs et
destructeur qui sont implicitement appeles respectivement lors de
la cration et la destruction d'un objet.

Le(s) constructeur(s) sont des fonctions membres qui portent le


mme nom que leur classe. Ces constructeurs sont appels aprs
l'allocation de l'espace mmoire destin l'objet.
Un constructeur peut tre surcharg et avoir des arguments par
dfaut.
Classes & objets

Constructeur / Destructeur (suite)


Exemple:
Class Point
{
int x;
int y;
public:
Point(int,int); // constructeur
void deplace(int,int);
void affiche();
};
Dans cet exemple, la dfinition du constructeur sera de la forme:
Point::Point(int abs, int ord)
Remarque: Mme si le constructeur ne retourne aucune valeur,
{
il est dclar et dfini sans le mot cl void .
x = abs;
y = ord;
}
Classes & objets

Constructeur/Destructeur (suite 2)
Pour dclarer une instance d'une classe ayant un constructeur, on
doit spcifier les valeurs des arguments requis par le constructeur.
Point A(2,5);

Point B; // erreur , car on a dclar la faon de construire les objets


Le destructeur est une fonction membre qui porte le mme nom que
sa classe, prcd du symbole (~). Le destructeur est appel avant la
libration de l'espace associ l'objet.
Un destructeur ne peut pas tre surcharg.

Exemple:
class Point {
int x;
int y;
public:
Point(int,int); // constructeur
~Point(); // destructeur Dans cet exemple, la dfinition du destructeur sera de la forme:
Point::~Point() { }

};
Classes & objets

Constructeur/Destructeur
Le destructeur est une fonction qui ne prend aucun argument et
ne renvoie aucune valeur.
En pratique les destructeurs sont utiliss pour librer
d'ventuels emplacements mmoire occupe par des membres
donnes.
Classes & objets

Exemple:
Considrons par exemple une classe Tab_entiers, qui permet de traiter des tableaux d'entiers dont les
dimensions sont fournies en donnes. Le constructeur aura donc la tche d'allouer dynamiquement
l'espace mmoire ncessaire pour l'instance crer et le destructeur doit librer cette zone.

/*------------------- dfinition du constructeur ---------------------*/


class Tab_entiers Tab_entiers::Tab_entiers(int n)
{ {
nb = n;
int nb; tab = new int [nb];
}
int * tab; /*------------------ dfinition du destructeur -----------------------*/
Tab_entiers::~Tab_entiers()
public:
{
Tab_entiers(int); // constructeur delete tab;
}
~Tab_entiers(); // destructeur

};
Classes & objets

Exercice:
1) On dsire munir la classe Point d'un constructeur qui permet de crer le
point :
(0,0) si aucun argument n'est fourni

(abs,0) si on lui fournit abs comme seul argument

(abs,ord) si on lui fournit les deux arguments abs et ord

2) On dsire maintenant que le constructeur de la classe Point crer le point


(abs,abs) si on lui fournit un seul argument (abs)
Classes & objets

Affectation entre objets


C++ autorise l'affectation d'un objet d'un type donne un autre
objet de mme type. Dans ce cas il recopie tout simplement les
valeurs des membres donnes (privs ou publiques) de l'un dans
l'autre.
Point A,B; // dclare deux instances de la classe Point
A.initialise(2,5); // A.x = 2 et A.y = 5
B =A; // B.x = 2 et B.y = 5
Il faut noter que les pointeurs ne sont pas pris en considration dans
un cas simple d'affectation : Si parmi les membres donnes, se
trouve un pointeur, l'emplacement point ne sera pas recopi (voir
surcharge des oprateurs).
Classes & objets

Attribut statique
Un membre donne dclar avec l'attribut static est une donne
partage par toutes les instances d'une classe.
Un membre donne statique est initialis par dfaut zro. Mais :
Il doit tre dfini l'extrieur de la dclaration de la classe, mme s'il est priv, en
utilisant l'oprateur de port (::).

Ne peut tre initialis l'intrieur de la classe.

L'accs un membre donne statique d'une classe suit les mmes


rgles que les autres membres. D'autre part, un membre donne
statique est une donne qui existe mme si aucun objet de cette
classe n'est dclar, dans ce cas l'accs se fait l'aide du nom de la
classe et l'oprateur de port (::).
Classes & objets

Exemple:
class cpt_obj

static int nb_obj;

int a;

public:

cpt_obj(int); // constructeur

};

/*-------------------------------- dfinition du membre statique -----------*/

int cpt_obj::nb_obj; // par dfaut nb_obj=0

/*------------------------ dfinition du constructeur -------------------------*/

cpt_obj::cpt_obj(int n) {

a = n;

cpt_obj++;

}
Classes & objets

Exploitation des classes dans des projets C++:


Pour les applications ncessitant beaucoup de classes, il est souhaitable
que celles-ci figurent dans des fichiers diffrents. On travaille alors de
la manire suivante :
- les dclarations des classes sont faites dans des fichiers dextension
.h (fichiers dentte)

- les dfinitions des fonctions membres sont dans des fichiers


dextension .cpp
- lutilisation de ces classes apparat finalement dans un fichier
dextension .cpp contenant la fonction void main(void).
Classes & objets

Exemple:
Classes & objets

Exemple:

#ifndef, #define et #endif sont ajouts aux fichiers include pour que le
fichier ne soit inclus quune seule fois lors dune compilation.
Enfin, dans tout programme utilisant la classe nom_classe, on doit
inclure le fichier d'entte ''nom_classe.h''. Un tel programme doit
aussi pouvoir accder au module objet rsultant de la compilation du
fichier source contenant la dfinition de la classe.
Classes & objets

Objets transmis en argument:


Considrons une classe T et une fonction F dont l'un des paramtres
est un objet de T transmis par valeur, par adresse ou par rfrence.
Soit U une instance de T transmis en argument F, alors:
1. Si F est une fonction membre de T, elle aura accs tous les
membres donnes de U, sinon elle n'aura accs qu'aux membres
publiques de U.
2. Si la transmission de U se fait par valeur, il y a recopie des membres
donnes de U dans un emplacement locale F, ce qui entrane
certains problmes si la classe contient des pointeurs.
Classes & objets

Exemple:
Dfinir une fonction qui permet de comparer deux instances de la classe
Point. Cette fonction devra retourner "true" si les deux objets
concident et "false" sinon.

La comparaison ncessite l'accs aux coordonnes des points, qui sont


des donnes privs, par suite, la fonction doit tre une fonction
membre de la classe.
La dclaration de la fonction dans la classe sera :
bool coincide(Point);

Et sa dfinition:
bool Point::coincide(Point pt)

return ( (pt.x == x) && (pt.y == y));

}
Classes & objets

Objet fourni en valeur de retour


Etant donn une classe T et une fonction F qui a l'une des formes
suivantes : T F(arguments); // retour par valeur
T * F(arguments); // retourne l'adresse
T & F(arguments); // retourne une rfrence
Alors F aura accs tous les membres de l'objet retourn si elle est une
fonction membre de T, si non elle n'aura accs qu'aux membres publics de
la classe.
Notez bien que d'une manire gnrale, une fonction ne doit pas retourner un
pointeur (ou une rfrence) sur une variable locale, du fait que la zone
mmoire occupe par une variable locale une fonction est
automatiquement considre comme libre la fin de la fonction. Ainsi, par
exemple :
int * fct_adr() { int n; , return &n}
int & fct_ref() { int n; , return n}
fournirons des rsultants imprvisibles et errons.
Classes & objets

Exemple:
On dsire dfinir la fonction symetrique() qui permet de retourner le symtrique
d'un point de la classe Point.
Cette fonction doit tre une fonction membre de la classe Point, puisqu'elle doit
accder aux coordonnes du point, qui sont des donnes prives. La valeur
de retour sera de type Point La dclaration de la fonction dans la classe sera
:
Point symetrique();

et sa dfinition
Point Point::symetrique()

Point pt;

pt.x = -x; pt.y = -y;

Return pt; Question: Peut-on transformer cette fonction pour qu'elle fournisse un pointeur
(ou une rfrence) du rsultat ?
} Non, puisque le calcul du rsultat doit se faire sur une variable locale la fonction.
Classes & objets

Le pointeur this
En C++, tous les objets possdent un champ priv particulier nomm this, sans quil
soit ncessaire de le dclarer. Ce champ contient ladresse de lobjet courant.
Dans une fonction membre, this reprsente un pointeur sur l'instance ayant
appel cette fonction
this est un pointeur constant, c'est--dire qu'on ne peut le modifier.
Exemple:
class Point { point::point(int abs, int ord) { x = abs; y = ord;}
int x; int y; void point point::affiche()
{
public: cout << " le point : (" <<this x << "," << this y << ")" ;
cout << " est l'adresse " << this << endl;
point(int=0, int=0); }
void affiche();

};
Classes & objets

Fonctions membres statiques


On distingue deux types de membres :
Membres d'instance : membres associs une instance de la classe.
Membres de classe : membres associs la classe et qui ne dpendent d'aucune
instance de la classe.

Les membres de classe, sont aussi dits membres statiques. Ils sont
dclars avec l'attribut static, et existent mme si aucun objet de la
classe n'est cre.
Ainsi on peut dfinir un membre donne statique comme on peut
dfinir une fonction membre statique. L'accs ces membres se fait
avec l'oprateur de rsolution de porte (::) prcd par le nom de la
classe ou d'un quelconque objet de la classe
Classes & objets

Exemple:
// Interface de la classe : POINT.H // Corps de la classe : POINT.CPP
#include "Point.h"
#ifndef POINT_H // definition obligatoire du membre donn statique
#define POINT_H int point::nb_obj;
Point::Point(int abs, int ord)
#include <iostream.h> // utilis dans affiche() {
x = abs; y = ord;
class Point{ nb_obj++;
}
int x; Point::~Point()
{
int y;
nb_obj--;
static int nb_obj; }
void Point::affiche()
public: {
cout << "(" << x << "," << y << ")" << endl;
Point(int = 0, int = 0); }
// definition de la fonction membre static
~Point(); void Point::affiche_nbobj()
void affiche(); {
cout<<''le nombre d'objets est''<<nb_obj<<endl;
static void affiche_nbobj(); }
----
};

#endif
Classes & objets

Exemple (suite)
// Programme test

#include "Point.h"

void main()

{ //acces la fonction membre static avant la cration des objets

Point::affiche_nbobj();

// cout << Point::nb_obj ; // erreur : nb_obj est prive

// Appel de la fct membre en utilisant un objet

Point A;

A.affiche_nbobj();

// Appel de la fonction membre statique en utilisant le nom de la classe

Point B(5,6);

Point::affiche_nbobj();

}
Classes & objets

Les fonctions membres constantes


Les objets, comme les autres types de C++, peuvent tre dclares
constants avec l'attribut const. Dans ce cas, seules les fonctions
membres dclares et dfinies avec l'attribut const peuvent tre
appeles par des objets constants.
Exemple:
class T { ... // dclarations
T u; // instance non constante
public:... const T v; // instance constante
// appels
type_a F(...); // fct membre ordinaire u.F(); // OK
type_b G() const; // fct membre constante v.F() ; // erreur: instance constante
u.G() ; // OK
type_c K(const T); // fct avec argument constant v.G(); // OK

}; T w;
u.K(v); //OK
u.K(w); // OK
v.K(w); // erreur:instance constante et fct non constante

Remarque: Une mthode constante peut tre appele sur un objet variable
ou constant.
Classes & objets
On adoptera donc la discipline de programmation suivante :
. mthode daccs aux donnes ou accesseur : il sagit des
mthodes qui retournent ou affichent des donnes de lobjet sans les
modifier. Les accesseurs doivent tre des mthodes constantes.
. mthode de modification des donnes ou modificateur ou
mutateur : il sagit des mthodes qui modifient les donnes de
lobjet. Un modificateur ne doit donc pas tre appel sur un objet
constant. Par consquent, un modificateur ne doit surtout pas tre
dclar comme mthode constante.
Classes & objets
Dclaration et initialisation des objets
Les objets suivent les mmes rgles que les variables ordinaires, nous
distinguerons alors :

Les objets globaux : ceux qui sont dclars en dehors de tout bloc.
Les objets automatiques : ceux qui sont dclars au sein d'un bloc
Les objets statiques : ce sont les objets locaux statique (dfinie avec le
mot cl static)
Classes & objets
Cas d'une classe sans constructeur
Les donnes membres des objets globaux et statiques, qui ne sont pas
des pointeurs, seront initialiss par dfaut 0.
L'initialisation explicite des objets lors d'une dclaration ne peut se faire
qu'avec des objets de mme type, comme par exemple :
T a;
T b = a;
o T est une classe. Dans ce cas, le compilateur fera une copie simple
des valeurs des membres donnes de a dans ceux de b.
Notez que, l'utilisation d'une classe sans constructeur et comportant un
pointeur est fortement dconseille, du fait qu'aucune initialisation
implicite ne sera parfaite et que lors de l'initialisation d'un objet par un
autre, les deux objets concerns partageront la mme zone mmoire
pointe par le pointeur
Classes & objets
Cas d'une classe avec constructeur
Pour une telle classe, toute dclaration doit comporter une initialisation.
Ainsi, pour dclarer par exemple un objet u d'une classe T, on doit
utiliser l'une des syntaxes suivantes :
syntaxe 1: T u=v;
syntaxe 2: T u(liste_des_valeur);
syntaxe 3: T u = T(liste_des_valeur);
Dans syntaxe 1, v est un objet de la classe T (dfini antrieurement).
Les syntaxes 2 et 3 sont quivalentes. Dans ces deux formes,
liste_des_valeur est une liste de valeurs qui correspond la liste des
arguments du constructeur, en tenant compte des valeurs par dfaut
dfinies par le constructeur et des surcharges ventuelles du
constructeur (autrement dit, T(liste_des_valeurs) doit tre un appel
valable de la fonction membre T)
Classes & objets

Exemple:
class T {
int i;char c;
public:
T(int n, char cc = 'a' ){i=n; c=cc;}

};
T a(5,'A'); // ou T a=T(5,'A')
T b = T(3); // ou T b(3) et quivalent T b(3,'a')
T c = a;
Classes & objets
Cas d'une classe avec constructeur (suite)

Par ailleurs, notons les cas particuliers suivants:

Si tous les arguments du constructeur ont une valeur par dfaut


T u(); et T u; seront quivalentes.
Si la classe ne comporte qu'un membre donne du type de base
T u(valeur); et T u = valeur; seront quivalentes. Dans la deuxime il y aura
une conversion implicite du type de valeur vers T.
Exemple:
class T{
float z;
public:

T(float x =0.0){z=x;}

};

//La dclaration

T u = 1.2; //conversion implicite float->T


Classes & objets
Constructeur par recopie (copy constructor)
Considrons une classe T, dont l'un des membres donnes est un
pointeur nomm adr. Cette classe doit alors comporter un
constructeur qui alloue dynamiquement une zone mmoire ce
pointeur pour l'initialiser et un destructeur qui libre cette zone
mmoire lors de destruction des objets. Dans ce cas, si
T u = v; // o v est un objet de la classe T

Il y aura une copie simple des valeurs des membres donnes de v dans
ceux de u. Par suite, les pointeurs u.adr et v.adr dsigneront la
mme adresse, ce qui posera deux problmes :
Toute modification contenu de *adr de l'un des objets se fera aussi
pour l'autre.
La destruction de l'un des objets, entranera la destruction du pointeur
du deuxime.
Classes & objets
Exemple
#include <iostream.h> // --------------- Dfinition des fonctions membres
T::T(int n, int p)
//------------ Dclaration de la classe {
i = n;
class T{ pi = new int;
*pi = p;
int i; }
int *pi; T::~T()
{
public: if(pi != NULL)
delete pi;
T( int = 0, int = 0); }
void T::affiche()
~T(); {
cout << "(" << i << "," << *pi << ") --> " << pi <<
void affiche();
endl;
void modifier(int,int); }
void T::modifier(int n, int p)
}; {
i = n ; *pi = p;
}
Classes & objets

Exemple (suite)
// ----------------------------------------- Test

void main()

T u;

cout << "u : ";u.affiche();

// initialisation d'un objet avec un autre

T v = u;

cout << "v : ";v.affiche();

// on modifie v

cout << "\n------------Modification" << endl;

v.modifier(2,2);

cout << "v : ";v.affiche();

cout << "u : ";u.affiche();

}
Classes & objets
Constructeur par recopie (suite)
Pour rsoudre ce type de problmes, C++ offre la possibilit de dfinir un
constructeur particulier appropri ce genre de situation. Ce constructeur est
appel constructeur par recopie (copy constructor) et il est dclar comme suit:
T ( T &);

Le code du constructeur par recopie doit contenir les instructions ncessaires


pour crer un nouvel objet partir de l'objet pass en paramtre.
Exemple:
On ajoute la classe T de l'exemple prcdent , un constructeur par recopie dfinie
comme suit :
T::T( T & v)
{
i = v.i;
pi = new int;
*pi = *(v.pi);
}

et on refait le mme test que dans l'exemple prcdent, pour montrer que les
problmes poss par l'initialisation d'un objet par un autre sont bien rsolus.
Classes & objets
Tableau d'objets
En thorie, un tableau peut possder des lments de n'importe quel
type. Ainsi nous pouvons dclarer un tableau de N objets d'une classe T
par :
T tab[N];
Or, du fait qu'on ne peu dclarer un objet sans l'initialiser, cette dclaration ne
sera possible que si la classe T admet un constructeur sans arguments (ou
un constructeur dont tous les arguments ont des valeurs par dfaut).
Ces mmes remarques s'appliquent pour les tableaux dynamiques d'objets.
Une dclaration de type :
T * adr = new T[N];
ncessite aussi un constructeur sans arguments.
Classes & objets
Objet d'objets
Une classe peut comporter un membre donne de type classe.
Considrons alors la situation suivante, o la classe T comporte un
membre donne de type classe A :
class A{

public:
A(liste_arguments_a);

};
class T{
A a;

public:
T(liste_arguments);
Classes & objets
Objet d'objets (suite)
Lors de la cration d'un objet de type T, il y aura appel du constructeur de T puis un appel
du constructeur de A, car la cration d'un objet ncessite la dfinition de tous les
membres donnes de l'objet (en particulier le membre a de type A).
Par suite, la cration d'un objet de type T ne sera possible que si A possde un
constructeur sans arguments.

Pour grer ce genre de situation, C++ nous offre la possibilit de mentionner,


dans la dfinition du constructeur de T, la liste des arguments fournir au
constructeur de A et ce de la manire suivante :
T::T (liste_arguments) : a (liste_arguments_a)
{}

o liste_arguments_a est une sous liste de liste_arguments, valable pour le


constructeur de A.
Classes & objets
Fonctions amies
Si une fonction Fct est amie (friend) dune classe C1, alors Fct peut
accder aux champs privs de C1.
Si une classe C2 est amie de C1, toutes les fonctions membres de C2
peuvent accder aux champs privs de C1.
Ces dclarations se font dans la dfinition de C1 :
c l a s s C1 {

...

f r i e n d type-ret Fct( paramdeF ) ;

f r i e n d c l a s s C2 ;

...

};
Classes & objets
'Friend' en rsum
Les amis dune classe sont des classes ou des fonctions
Les amis dune classe peuvent accder toutes les mthodes
et donnes membre de la classe quel que soit le niveau de
protection
Les amis dune classe sont dfinis lintrieur de la classe
Violation parfois utile, mais trs souvent dconseille du
principe d'encapsulation
Classes & objets
La surcharge des oprateurs
En C++, les oprateurs dfinis pour les types de base sont traits par le
compilateur comme des fonctions, ce qui permet donc, avec la
technique de la surcharge, d'utiliser la plus part d'entre eux avec les
types classe
Les oprateurs redfinissables sont :

Les oprateurs qui ne peuvent tre surchargs .


. .* :: ?: # ##
Classes & objets

Pour surcharger un oprateur X, on dfinit la fonction operatorX (par


exemple operator+ pour l'addition).
L'implmentation de la surcharge d'un oprateur peut se faire soit
comme une fonction classique (amie d'une classe), soit comme une
fonction membre d'une classe.
La surcharge d'un oprateur est appele implicitement par le
compilateur chaque fois que l'oprateur est rencontr dans le code,
mais elle peut tre aussi appele explicitement.
Classes & objets
Surcharge d'oprateurs : SYNTAXE DE DECLARATION

Syntaxe gnrale :
type_de_retour operator op(liste arg);

Le symbole op qui suit le mot cl operator doit obligatoirement tre un


oprateur dj dfini pour les types de base

Exemple :
class Point {int x,y; };
Prototype de la fonction amie operator + :
Point operator +(Point,Point) ;

Prototype de la fonction membre operator + :


Point operator +(Point) ;
Classes & objets
Surcharge d'oprateurs (suite)
La surcharge doprateurs doit conserver la pluralit (unaire,binaire) de
loprateur initial
Oprateurs unaires : + - ++ -- ~ * & new delete (cast), etc ...
Oprateurs binaires:
* / % + - << >> < <= > >= || && | & [], etc
Loprateur . ne peut pas tre surcharg
Les oprateurs =,[], (), ->, new et delete doivent tre redfinis comme
fonctions membre d'une classe (et non comme fonctions amies)
Classes & objets
Surcharge d'oprateurs: Fonction amie
Les arguments de la fonction correspondent aux oprandes de
loprateur
Au moins un des arguments est de type classe
Exemple :
class Point {int x,y; };
Prototype de la fonction amie operator +:
Point operator +(Point,Point) ;
dclarer lamiti dans la classe Point
dfinir la fonction amie
Classes & objets
Surcharge d'oprateurs (suite)
Exemple:
main()
#include <iostream.h> {
class Point Point a(1,2), b(2,5) ;
{ int x,y ; Point c ;
c=a+b;
public : }
Point (int abs = 0 , int ord = 0)
{x=abs; y=ord; } Remarques :
friend Point operator+ (Point,Point) ; expression a+b interprte par le compilateur
comme lappel : operator+ (a,b)
};
on pourrait crire :
c = operator +(a,b);
Point operator + (Point a, Point b)
{ Point p ;
p.x = a.x + b.x ; p.y = a.y + b.y ;
return p ;
}
Classes & objets
Surcharge d'oprateurs: Fonction membre
La premire oprande de loprateur transmise implicitement :
lobjet auquel on applique la fonction membre
Si loprateur est binaire, pas de contrainte de type impos sur
largument explicite
Exemple :
class Point {int x,y; };
Prototype de la fonction membre operator + :
Point operator +(Point) ;
Classes & objets
Surcharge d'oprateurs (suite)
Exemple:
#include <iostream.h>
main()
{
class Point
Point a(1,2), b(2,5) ;
{ x,y ; Point c ;
public : c=a+b;
Point (int abs = 0 , int ord = 0) }
{x=abs; y=ord; }
Point operator+ (Point) ; Remarques :
}; expression a+b interprte par le compilateur
comme lappel : a.operator+ (b)
on pourrait crire :
Point Point :: operator + (Point b)
c = a.operator +(b);
{ Point p ;
p.x = x + b.x ; p.y = y + b.y ;
return p ;
}
Classes & objets
Surcharge d'oprateurs (suite): Passage par rfrence
La transmission des arguments peut se faire par rfrence
(prfrable pour objets de grande taille)
Prototype de la fonction amie :
Point operator +(Point & a, Point & b) ;
ou
Point operator +(const Point & a, const Point & b) ;
Prototype de la fonction membre :
Point operator +( Point & b) ;
ou
Point operator +(const Point & b) ;
Classes & objets
Surcharge d'oprateurs: oprateur d'affectation
Exemple :
Point a(1,2), b(3,4) ;
...
b=a;
Si non explicite, oprateur daffectation par dfaut : recopie des
valeurs de la seconde oprande dans la premire
Doit tre dclar comme une fonction membre en C++

Diffrences entre l'implmentation du constructeur par recopie et


celle de la surcharge de l'oprateur =:
affectation d'un objet lui-mme possible

avant affectation : 2 objets dj construits


Classes & objets
Forme canonique d'une classe
class A
{
public:
A() ; // constructeur
A(const A &) ; // constructeur de recopie
~A() ; // destructeur
A & operator = (const A &) ; // oprateur daffectation
};
Classes & objets
Surcharge d'oprateurs: oprateur de
conversion

Si un oprateur de conversion est dfini, on peut affecter


lobjet dans une variable du type correspondant

Doit tre dclar comme une fonction membre en C++

Pas de type de retour spcifi :


type = nom de loprateur

Pas de paramtre

Retour de lobjet converti


Classes & objets
Surcharge d'oprateurs: oprateur de conversion

Dfinition :
class Point
{
public:
operator double(); // oprateur unaire
private:
int x,y ;
};

Implmentation :
Point::operator double()
{
return sqrt(x*x+y*y) ;
}

Utilisation :
main()
{
Point pt(10,3) ;
double f ;
f = (double)pt ; // ou double (pt) ;
}
HERITAGE
A l'origine

Impratif de rutiliser les portions de code


dj crites dans les classes utilises pour
des projets antrieurs (comme cela se fait
dans les modules en C).

Pourquoi?

recopier est peu valorisant

recopier est coteux en dveloppement (criture,
mise au point, tests)

recopier est coteux en maintenance
(multiplication des erreurs)
HERITAGE
L'ide

Organiser ses propres classes en rutilisant


les classes existantes (les siennes ou celles
des autres (bibliothques,))

Une classe drive hrite de (rcupre)


toutes les donnes membre et toutes les
fonctions membre de la classe de base
HERITAGE

L'ide (suite)

Une classe drive peut



accder aux donnes membre et fonctions
membre de sa classe de base selon certaines
rgles
(accs si public ou protected)

ajouter des donnes membre et fonctions
membre sa classe de base

redfinir* certaines fonctions membre de sa
classe de base
(*) dfinir des fonctions aux en-ttes identiques, savoir noms identiques et
paramtres identiques. Diffrent de la surdfinition ou surcharge!
HERITAGE
Le Principe

L'hritage simple structure un ensemble de


classes en une hirarchie.

Au sommet, on trouve la classe


correspondant au concept le plus gnral.

Du sommet vers la base, on spcialise en


cas de plus en plus particuliers.

La relation d'hritage:

est_un

possde les caractristiques de
HERITAGE
Le principe (suite)

Vhicule

Vhicule

Avion Voiture Bateau


Avion Vhicule Voiture Bateau

Avion Voiture Jeep


Bateau Voilier
Jeep Voilier

Hydravion Jeep Voilier


HERITAGE
Rsum

Permet de dfinir une classe qui enrichit ou


spcialise une classe existante

On peut driver de une ou plusieurs classes


(hritage multiple trs dangereux)

La classe drive peut accder aux membres


publics et protgs de la classe de base

La classe drive ne peut pas accder aux


membres privs de la classe de base
HERITAGE
Syntaxe

Hritage simple :

class MaClass : public MaClass_de_base


{
...
};

Hritage multiple :

class MaClass : public MaClasse_de_Base , public AutreClasse_de_deBase


{
...
};
HERITAGE
Construction

Quand un objet est construit, tous les


constructeurs sont appels

Les constructeurs des classes de base


sont appels AVANT les constructeurs des
classes drives

Exemple : Si A drive de B qui drive de


C:

Le constructeur de C est appel

Le constructeur de B est appel

Le constructeur de A est appel
HERITAGE

Exemple
class D
{public :
D(int,int) ;
};
class E : public D // E drive de D
{public :
E(int,int,int) ;
};
// initialisation de la classe de base
E::E(int x,int y,int z) : D(x,y)
{
}
HERITAGE
Constructeurs

CAS 1 : Cas o le constructeur de la classe drive est synthtis par le
compilateur (sans paramtres) : ce constructeur appelle le constructeur par
dfaut de la classe de base (appel sans argument du constructeur synthtis
ou d'un constructeur dfini sans paramtres ou dont tous les paramtres ont
une valeur par dfaut)
class A class A
class A { {
{ private: private:
private: public: public:
public: A(); A(T1 a1, T2 a2);
}; }; };

class B : public A class B : public A class B : public A


{ { {
private: private: private:
public: public: ...}; public:
}; OK : le constructeur synthtis de B };
appelle le constructeur par dfaut A NON : le constructeur synthtis de B ne trouve
OK : le constructeur synthtis de B appelle dfini sans paramtres pas de constructeur par dfaut (dfini sans
le constructeur par dfaut A (ici synthtis) paramtres ou avec paramtres par dfaut)
dans A
HERITAGE
Constructeurs (suite)

CAS 2 : Un constructeur explicitement dfini de la


classe drive appelle le constructeur de la classe de
base en accord avec la liste d'initialisation dans l'en-
tte de sa dfinition. Si la liste ne mentionne pas de
constructeur, c'est le constructeur par dfaut qui est
appel (sans paramtres).
HERITAGE
Appels Constructeurs
class A
{
private:
public:
A(T1 a1, T2 a2);
};

class B : public A // B drive de A


{
private:
public:
B(T1 b1, T2 b2, T3 b3);
};

// dfinition des mthodes


B::B(T1 b1, T2 b2, T3 b3) : A(b1,b2)
{
}
OK : le constructeur de B appelle le constructeur de A prcis dans la liste
d'initialisation.
HERITAGE
Appels Constructeurs
class A
{
private:
public:
A();
A(T1 a1, T2 a2);
};
class B : public A
{
private:
public:
B(T1 b1, T2 b2, T3 b3);
};
// dfinition des mthodes
B::B(T1 b1, T2 b2, T3 b3)
{
} OK : le constructeur de B appelle le constructeur par dfaut (sans paramtres et non
synthtis ici) de A
HERITAGE
Appels Constructeurs
class A
{
private:
public:
};

class B : public A
{
private:
public:
B(T1 b1, T2 b2, T3 b3);
};

// dfinition des mthodes


B::B(T1 b1, T2 b2, T3 b3)
{
}

OK : le constructeur de B appelle le constructeur par dfaut


(synthtis) de A .
HERITAGE
Appels Constructeurs
class A
{
private:
public:
A(T1 a1, T2 a2);
};
class B : public A
{
private:
public:
B(T1 b1, T2 b2, T3 b3);
};
// dfinition des mthodes
B::B(T1 b1, T2 b2, T3 b3)
{
}

NON : le constructeur de B ne trouve pas le constructeur par dfaut de A . Pas de


constructeur synthtis ici.
HERITAGE
Destruction

Quand un objet est dtruit, son destructeur et


celui de toutes les classes de base sont appels

Le destructeur de la classe drive est appel


en premier

Exemple : Si A drive de B qui drive de C :



Le destructeur de A est appel

Le destructeur de B est appel

Le destructeur de C est appel
HERITAGE
Accs aux membres
Statut des membres de la classe drive en fonction du
statut des membres de la classe de base et du mode de
drivation.

- les attributs privs, mais accessibles par linstance


- les attributs inaccessibles : ils occupent de la place mmoire, mais personne ne peut plus
y accder, y compris linstance elle-mme.
HERITAGE
Hritage priv

But : masquage du legs de la classe de base reu par la classe drive


= technique de fermeture des accs la classe de base

Syntaxe :
class MaClass : private MaClasse_de_Base
{
...
};

1) Un utilisateur de la classe drive MaClass ne pourra pas accder aux membres


publics de la classe de base

2) Les fonctions membres de la classe drive peuvent accder aux fonctions et


membres publics et protgs de la classe de base
HERITAGE
Hritage priv (suite)

Quand lutiliser ?
Toutes les fonctions utiles de la classe de
base sont redfinies dans la classe
drive et on ne veut pas laisser
lutilisateur du programme accder aux
fonctions de la classe de base
(exemple : Pile drive de Tableau)
HERITAGE
Hritage priv (suite)
Ce type d'hritage s'utilise lorsque la classe drive n'est pas un cas particulier
Exemple: de la classe de base (bien que sa dfinition s'appuie sur celle de la classe de
base).
class Table class Pile : private Table
{ {
int nb; double *sommet;
double *tab; public:
public: Pile();
Table(); Pile(int taille);
Table(int taille); void empiler(double x);
Table(const Table&); double depile();
~Table(); bool isEmpty();
Table& operator=(const Table&); };
double& operator[](int);
};
L'implmentation de Pile s'appuie sur celle de Table, mais il est ncessaire de cacher l'utilisateur la
possibilit d'accder n'importe quel lment de la pile par l'oprateur []; pour cette raison on choisit
lhritage priv.
HERITAGE
Rtablissement des droits d'accs
Il est possible de rtablir les droits d'accs modifis par la drivation pour
rtablir les droits d'origine de ces attributs ou mthodes.
Le rtablissement ne concerne que les membres dclars public ou
protected dans la classe de base.
class A
class B : private A int main()
{
{ {
public: public: B b;
using A::a1; b.a1 = 1; // OK
int a1; }; b.a2 = 1; // Illgal
int a2; return 0;
};
};
HERITAGE

Constructeur par copie


Rappel : le compilateur gnre un constructeur par copie trivial si le
concepteur n'en crit pas.
Le constructeur par copie gnr pour une classe drive appelle
implicitement les constructeurs par copie des classes de base. Ce n'est pas
le cas si on crit soi-mme le constructeur par copie.
HERITAGE
Constructeur par copie
HERITAGE
Constructeur par copie
La meilleure solution consiste l encore utiliser les listes
d'initialisation des constructeurs :
HERITAGE
Oprateurs

Tous les oprateurs sont hrits

Attention loprateur = (affectation) :


surcharge de loprateur = dans la classe drive
: il faut appeler celui de la classe de base (pas dappel
implicite comme dans le cas du constructeur)
HERITAGE
Oprateurs (suite)

Si oprateur = non surcharg dans la classe


drive:

affectation de la partie hrite de la classe de base
selon la surcharge de l'oprateur = dans la classe de
base

affectation membre membre (par dfaut) pour les
membres propres la classe drive
HERITAGE
Redfinition des attributs
Il est possible de redfinir un attribut dans la classe drive. L'attribut
redfini masque celui issu de la classe de base. L'oprateur de
rsolution de porte (::) permet cependant d'accder l'attribut
masqu :
class A int x;
{ void B::f() Trois variables de
public: { mme nom !!!
int x; x++; // incrmente B::x
}; A::x++; // incrmente A::x
class B : public A ::x++; // incrmente x global
{ };
public:
int x;
void f();
};
HERITAGE
Redfinition des mthodes
De la mme faon, une mthode masque toutes les
mthodes de mme nom dfinies dans la classe de base.
class A int main()
{ {
public: B b;
void f(int); b.f(1); // Erreur : 'f' fonction ne prend pas de paramtre
void f(); b.A::f(1); // OK
}; b.f(); // OK, appelle B::f()
class B : public A return 0;
{ };
public:
void f();
};
HERITAGE
Conversions dobjets
Par un hritage public, une classe B drive de A est considre comme
une "sorte" de A. Quel que soit l'objet a de type A et l'objet b de type
B driv publiquement de A, tous les services offerts par a sont aussi
offerts par b
=> donc b peut remplacer a
Pour des classes en relation de drivation publique, le compilateur
effectue certaines conversions implicites :
objet de la classe drive => objet de la classe de base ;
rfrence sur un objet de la classe drive => rfrence sur objet
classe de base ;
pointeur sur un objet de la classe drive => pointeur sur objet classe
de base.
Cette conversion implicite n'existe pas si l'hritage est priv ou protg.
HERITAGE
Conversions dobjets (suite)
On ralise les appels :
X xob;
Soient les classes: Y yob;
class X {}; P pob;
class Y : public X {};
fx1(yob); // Classe drive => base
class P : private X {};
fx2(&yob); // Idem

fy1(xob); // Erreur, pas dans ce sens


fy2(&xob); // Erreur, pas dans ce sens

fx1(pob); // Erreur, hritage priv


fx2(&pob); // Erreur, hritage priv

xob = yob; // Classe drive => base


Et soient les fonctions yob = xob; // Erreur, pas dans ce sens
suivantes: xob = pob; // Erreur, hritage priv
void fx1(X x);
void fx2(X* x); Daprs les hritages choisis :
void fy1(Y y); Tous les Y sont des X , mais Tous les X ne sont pas des Y
void fy2(Y* y); Les P ne sont pas des X
Le compilateur se charge de raliser automatiquement les
conversions autorises (ici seulement de la classe Y vers la classe X).
HERITAGE
Conversions dobjets (suite)

Pour un pointeur ou une rfrence, il est possible de distinguer :


le type statique du pointeur/rfrence : il peut tre dtermin la compilation,
par une analyse statique du code source ;
le type dynamique : il est dtermin par la valeur courante, et peut changer en
cours d'excution.
HERITAGE
Conversions dobjets (suite)
Grce ces conversions implicites de pointeurs et de rfrences, tout
objet peut tre trait comme un objet plus gnral. Cela permet de
traiter collectivement un ensemble d'objets de types diffrents :
POLYMORPHISME
L'ide

Le polymorphisme :
dans le prolongement de la surdfinition et de la
redfinition.

Surdfinitionou surcharge (overloading): les fonctions ont le mme
nom, mais le compilateur les distingue par la liste de paramtres

Redfinition (overriding): les fonctions membre ont exactement le mme
en-tte (nom et paramtres identiques), mais le compilateur les distingue selon le
type dclar de l'objet auquel on les applique

Polymorphisme: les fonctions membre ont toujours le mme en-tte, mais le
compilateur gnre, pour celles qui sont dclares virtuelles , des instructions
supplmentaires qui permettent de les distinguer lors de l'excution selon le type
effectif de l'objet auquel on les applique, tout ceci dans les limites d'une mme
hirarchie d'hritage
METHODE VIRTUELLE

Lorsquune mthode est virtuelle dans une


classe de base, elle est toujours virtuelle
dans toutes les classes drives

Placer virtual avant le type de retour de la


fonction

On rpte virtual dans les classes


drives pour la clart (mais ce nest pas obligatoire)
METHODE VIRTUELLE (suite)

Remarque importante : Si p est dclar


comme un pointeur vers une classe de
base, p peut contenir un pointeur vers
n'importe quelle classe drive de cette
classe de base.
La conversion de PCDERIVEE ->
PCBASE est implicite.
Il est sous-entendu ici que la drivation est
publique
METHODE VIRTUELLE (suite)

L'appel dune mthode virtuelle n'est plus


traduit par un branchement une adresse
connue d'avance, mais par une srie
d'instructions capable de dterminer lorsque
le programme s'excute quelle adresse il
convient de se brancher.

Lorsquune mthode est virtuelle, cest


limplmentation de la classe de lobjet
auquel elle est applique qui est appele
METHODE VIRTUELLE(suite)

SYNTAXE DE DECLARATION
class A
{
public:
A() {} ;
virtual bool IsA() const ;
};

class B : public A
{
public:
B() {} ;
virtual bool IsA() const ;
// virtual est optionnel dans la classe drive
};
METHODE VIRTUELLE
SYNTAXE DIMPLEMENTATION
bool A::IsA() const
{
return TRUE ;
}

bool B::IsA() const


{
return FALSE ;
}

c.--d. rien de spcial


METHODE VIRTUELLE:
UTILISATION
B drive de A :

A* pA = new A ;
A* pB = new B ;
if (pA->IsA())
cout << "Objet de classe A ";
if (pB->IsA())
cout << " Objet de classe A ";
delete pA ;
delete pB ; // ERREUR !!!!
// Destructeur de B non appel

Rappel :
En POO, on considre quun objet dune classe drive peut remplacer un
objet de la classe de base
Mthodes virtuelles
Remarque:Toujours dclarer virtuel le destructeur dune classe de
base destine tre drive pour sassurer d' une libration complte
de la mmoire.

Pas dobligation de redfinir une mthode virtuelle dans les classes


drives
Possibilit de redfinir une mthode virtuelle dune classe de base,
par une mthode virtuelle ou non virtuelle dans une classe Drive

Attention!! Ncessit de respecter le prototype de la mthode


virtuelle redfinie dans une classe drive (mme arguments et
mme type retour)
METHODE VIRTUELLE PURE

Une mthode virtuelle pure est une mthode


virtuelle dclare dans une classe de base,
mais nayant pas dimplmentation dans cette
classe

Les autres mthodes de la classe peuvent


appeler cette mthode
METHODE VIRTUELLE PURE

SYNTAXE DE DECLARATION

Ajouter = 0 la fin de la dclaration de la


mthode

class X
{
// Dfinition dune fonction virtuelle pure
// =0 signifie quelle na pas de dfinition
// Attention, cest diffrent dun corps vide : { }

virtual bool IsA() const = 0 ;


};
CLASSE ABSTRAITE

Une classe abstraite est une classe qui contient au moins une
mthode virtuelle pure

Les classes drives dune classe abstraite sont abstraites tant


que toutes les mthodes virtuelles ne sont pas implmentes
(virtuelles pures)

On ne peut pas crer un objet dune classe abstraite

Mais possibilit de dfinir des pointeurs et des rfrences


sur une classe abstraite

Quand une classe est abstraite, il est obligatoire den driver et


dimplmenter toutes les mthodes virtuelles pures .
Les entres-sorties
Introduction
Dj rencontr :
int n ;
cin >> n ; // flot d'entre cin
cout << n ; // flot de sortie cout
cerr <<''message erreur''; //flot de sortie des erreurs
Flot = canal :
recevant de linformation, si flot de sortie
fournissant de linformation si flot dentre

Rle des oprateurs << et >> :


transfert
de linformation
formatage (ventuel)

cout = flot prdfini connect la sortie standard (cran)


(en C : fichier prdfini stdout)
cin = flot prdfini connect lentre standard (clavier)
(en C : fichier prdfini stdin)
Les entres-sorties
Hirarchie des classes IO
ios
io s
istream ostream

is tre a m o s tre a m
iostream

ifs tre a m o fs tre a m

fstream
Les entres-sorties
Classe OSTREAM
cout est un objet de la classe ostream
#include <iostream.h>
ou
#include <iostream>
using namespace std ;
oprateur << surcharg pour les types de base

ostream & operator << (type_de_base);

exemple: cout << "valeur : " << n ;


Les entres-sorties
Classe OSTREAM: Fonctions membres principales
ostream & put(char) ;
char c = 'a' ;
cout.put(c) ; // affiche le caractre c

ostream & write(const char *,int) ;

char ptr[ ] = "bonjour" ;


cout.write(ptr,5) ;
// affiche 5 caractres partir de l'adresse ptr
Les entres-sorties
Classe ISTREAM
cin est un objet de la classe istream
#include <iostream.h>
oprateur >> surcharg pour les types de base

istream & operator >> (type_de_base &) ;

exemple: cin >> n >> x ;


Les entres-sorties
Classe ISTREAM: Fonctions membres principales
int gcount() ;
// fournit le nombre de caractres lus par getline()

char ch[20] ;
int len ;
while (cin.getline(ch,20))
{ len = cin.gcount() ;
}
istream & read(char * t,int x);
// lecture de x bytes

char t[5] ;
cin.read(t,5) ;
Les entres-sorties
Connexion d'un flot un fichier
#include <iostream.h>
#include <fstream.h>
Ecriture dans un fichier :
crer un objet de la classe ofstream (drive de ostream)
ofstream fic_out ("fic",ios::out) ;

nom de fichier mode d'ouverture

Lecture d'un fichier :


crer un objet de la classe ifstream (drive de istream)
ifstream fic_in ("fic",ios::in) ;

nom de fichier mode d'ouverture


Les entres-sorties
Connexion d'un flot un fichier (suite)
Lecture et criture dans un fichier :
crer un objet de la classe fstream (drive de iostream, qui drive de
istream et ostream)

fstream fic ("fic",ios::in|ios::out) ;

Ouverture dun fichier : par le constructeur de la classe ou par la


mthode open des classes ifstream , ofstream et fstream
void open (const char * filename, openmode mode = in | out);
Fermeture du fichier :

fic.close() ;
Les entres-sorties
Exemple
Louverture dun fichier est ralis laide de la mthode open
commune aux 3 classes,
#include <fstream.h>
int main( void )
{
ifstream f1; // instanciation de lobjet
f1.open("essai1.tmp"); // ouverture du flux de donnes
ofstream f2("essai2.tmp"); // combinaison des oprations
// ... ... ... ... ...
}
Les entres-sorties
Exemple complet
But lire et crire 1, 2, 3 dans un fichier!
#include <fstream>

#include <fstream> main()


#include <fstream> {
Ecrire(''toto.txt'');
void ecrire(char * nom_fic) { Lire(''toto.txt'');
ofstream osf(nom_fic, ios::out);
}

osf<<1<<'' ''<<2<<'' ''<<3;

osf.close(); }

void lire(char * nom_fic){

int i; ifstream ifs(nom_fic);

while(!ifs.eof()){ ifs>>i; // ifs lit et met le rsultat dans la variable i

If (!ifs.eof()) cout <<i<<'' ''<<endl;}


Les entres-sorties
Surcharge des oprateurs << et >> pour les types utilisateurs
Oprateur prenant un flot en premier argument ,il doit tre redfinie en fonction
amie
ostream & operator << (ostream &, expression_de_type_classe &)
istream & operator >> (istream &, expression_de_type_classe &)
Valeur de retour obligatoirement gale la rfrence du premier argument
class point

{ int x, y ;

public :

point (int abs=0, int ord=0){ x = abs ; y = ord ; }

friend ostream & operator << (ostream &, point &) ;

friend istream & operator >> (istream &, point &) ;

};
Les entres-sorties
// Redfinition de loprateur << en fonction amie de la classe Point

ostream & operator << (ostream & sortie, point & p)

{ sortie << "(" << p.x << "," << p.y << ")" ; return sortie ; }

// Redfinition de loprateur >> en fonction amie de la classe Point

istream & operator >> (istream & entree, point & p) // Si la saisie a t correcte, on affecte p

{ char c = '\0' ; if (ok=true) { p.x = x ; p.y = y ; }

int x, y ; bool ok = true ; // Statut derreur du flot gr par


// un ensemble de bits dun entier
entree >> c ; // saisie dun caractre au clavier
// clear (activation de bits derreur)
if (c != '(') ok = false ;
// badbit (bit activ quand flot dans un tat irrcuprable)
else { entree >> x >> c ; // saisie de x (entier) // rdstate () pur activer le bit badbit sans activer les autres

// et dun autre caractre au clavier else entree.clear (ios::badbit | entree.rdstate () ) ;

if (c != ',') ok = false ; // on retourne le flux d'entre


return entree ;
else { entree >> y >> c ; // mme chose pour y }
if (c != ')' ) ok = false ; }

}
Les entres-sorties
int main()
{
point b
cout << "donnez un point : " ;
if (cin >> b)
cout << "Affichage du point : " << b << endl ;
else cout << "** information incorrecte" << endl ;
}
Patrons (Templates)
Patrons de fonctions
template <typename T> T min (T a, T b)
{
if (a < b) return a; Paramtre de type T
else return b ; (T = type quelconque)
} typename T ou class T

Condition dutilisation de la fonction min():


2 paramtres de mme type (ex. 2 int, 2 float, )

min (3,7) ;
min(5.6,9.8) ;

Le compilateur fabrique (instancie) automatiquement la


fonction min avec le type T utilis : cest une fonction patron
Patrons (Templates)
Patrons de fonctions

Pas possible de crer un .o dun patron de


fonction

le mettre dans un fichier .h


Patrons (Templates)
Patron de fonction : application un type classe
class Point
{
public :
Point(int abs = 0, int ord = 0)
{ x =abs ; y = ord; }

int operator < (Point b)


{
return x*x+y*y < b.x*b.x+b.y*b.y;
}
private :
int x,y ;
};

main()
{
Point p1(2,5), p2(1,8),p3 ;
p3 = min(p1,p2) ;
}
Patrons (Templates)
Patron de fonction: paramtres de type

plusieurs paramtres de type:


template <typename T, typename U> T fct(T a, T* b, U c)

Paramtres peuvent intervenir:



dans len-tte de dfinition

dans des dclarations de variables locales

dans des instructions de type new, sizeof(),
template < typename T, typename U> T fct (T x,U y,T z)
{
Ta;
U *b ;
b = new U[10] ;
int n = sizeof(T) ;

a=x+y+z;
return a ; }
Patrons (Templates)
Les patrons de classes

crire une dfinition de classe

Le compilateur ladapte diffrents types


template < typename T> class Point
{
public :
Point(T abs = 0, T ord = 0)
{ x =abs ; y = ord; } // dfinition en ligne
void affiche() ; // dfinition hors classe Exemple d'utilisation:
Point <int> p1(3,5) ;
private : Point <float> p2(3.5,6.7) ;
T x,y ;
};

template < typename T> void Point<T>::affiche()


{
cout << " coordonnees : "
<< x << " " << y << endl ;
}
Patrons (Templates)
Patrons de classes: O?

Pas possible de fournir un utilisateur une classe patron


toute compile
la mettre dans un .h (y compris la dfinition des fonctions
membres non en ligne)
Patrons (Templates)
Patron de classe : paramtres expression
Paramtre de type Paramtre expression

Exemple :

template <typename T, int n> class Tableau


{
T tab[n] ;
};

Les valeurs effectives devront tre des constantes:

Tableau <int,4> t1 ;
Tableau <float,100> t2 ;
La gestion des exceptions
Le principe de la gestion des exceptions par C++ est le suivant :
quand une fonction veut signaler une erreur, elle lance (throw) un objet
erreur ;
lorsque l'utilisateur veut grer l'erreur, il attrape (catch) l'objet lanc ;
une erreur non attrape conduit un arrt du programme.
Cette technique est suprieure celle du renvoi de codes d'erreurs :
elle n'accapare pas la valeur de retour des fonctions ;
elle ne fait pas intervenir de variables globales ;
elle ne ncessite pas de paramtres supplmentaires, l'objet erreur pouvant
vhiculer des informations aussi complexes qu'on le souhaite ;
elle peut signaler une erreur dans un constructeur ou un destructeur (qui n'ont
pas de valeur de retour).
La gestion des exceptions
On lve une exception par l'instruction throw suivie d'une expression
quelconque (entier, double, chane de caractres, objet, ...).

void ouvrir(char* name)


{
FILE *f;
f = fopen(name, "r");
if(f==NULL)
Exception de type int
throw(1);
}

void ouvrir(char* name)


{
FILE *f;
f = fopen(name, "r");
if(f==NULL)
Exception de type const char* throw("Pb de fichier");
}
La gestion des exceptions
Lorsqu'on lve un objet-exception, on peut vhiculer des informations
complexes (nom de la fonction, fichier source, numro de ligne, messages,
codes divers, ...) :

Fichier MonException.h
class MonException {
public:
char *msg1, *msg2;
MonException (char *s1, char *s2);
};

void ouvrir(char* name)


{
FILE *f;
f = fopen(name, "r");
if(f==NULL)
Exception de type MonException throw MonException("Probleme avec", name);
}
La gestion des exceptions
Interception d'une exception
Si on ne fait rien de plus que lever l'exception par throw, le programme
se terminera faute de gestion de l'erreur au niveau de l'appelant
( appel de la fonction terminate() dont on peut modifier le
fonctionnement en utilisant set_terminate()).
Pour de petits programmes ou en phase de mise au point, cela peut
suffire.
Si le programmeur veut grer son exception, il doit mettre en place :
un bloc rceptif try : il sera en mesure d'attraper une exception lance
par une des instructions contenues dans le bloc ;
des gestionnaires catch : un par type d'exception que l'on veut capturer
(correspondant au type de l'exception leve par throw).
La gestion des exceptions
Interception d'une exception
Pour que l'exception soit capture par le bloc try, il faut qu'il y ait un gestionnaire de
type compatible avec celui de l'exception lance :

int main()
{
try
{
// Demander a l'utilisateur d'entrer
void ouvrir(char* name) // un nom de fichier
{ ouvrir(filename);
FILE *f; // Utiliser le fichier ouvert pour
f = fopen(name, "r"); // lire des donnes
}
throw(1); catch (int n)
} {
if (n == 1)
std::cerr << "PB de fichier\n";
}
La gestion des exceptions
Interception des exceptions
A chaque type qui peut tre utilis pour lancer une exception, il faut prvoir un
gestionnaire (catch) adapt (si on veut attraper lexception, bien sr) :
void ouvrir(char* name)

FILE *f;

f = fopen(name, "r"); try {


ouvrir("input.txt");
if(f==NULL) }
catch (const char *s) {
throw("Pb de fichier"); std::cerr << s;
}
}

void ouvrir(char* name)

FILE *f;
try {
f = fopen(name, "r"); ouvrir("input.txt");
}
if(f==NULL) catch (MonException &e) {
std::cerr << e.msg1<< e.msg2;
throw MonException("Probleme avec",name); }
La gestion des exceptions
Interception des exception
S'il n'y a pas de gestionnaire de type compatible associ au bloc try, l'exception
n'est pas traite dans le bloc try, elle remonte de fonction appelante en fonction
appelante jusqu' trouver un gestionnaire compatible :

int main()
{
try
{
lire_donnees(); void lire_donnees()
... {
} try
catch(const char *s) {
{ ouvrir("in.txt"); void ouvrir(char* name)
std::cerr << s; ... {
} } ...
return 0; catch (int n) throw("Pb de fichier");
} { }
// fait quelque chose
}}
La gestion des exceptions
Interception des exceptions
La leve d'une exception s'apparente un branchement (goto). Les
instructions non excutes :
dans la fonction qui a lanc l'exception,
dans les fonctions rencontres lors de la remonte de la pile d'appels,
dans le bloc try qui a captur l'exception ,
... sont abandonnes.
Les variables locales ces fonctions sont dtruites (leurs destructeurs
sont appels).
La gestion des exceptions
Interception des exceptions
Un bloc try peut tre suivi de plusieurs gestionnaires catch. Dans ce cas,
ces gestionnaires sont essays squentiellement suivant l'ordre de leur
dfinition, et ce sera le premier compatible qui sera excut.
int main() {
try {
...
}
catch (const char *s) { std::cerr << s;}
catch (int n) { if (n==1) std::cerr << "PB de fichier";}
catch (MonException &e) { std::cerr << e.msg1 << e.msg2;}
return 0;
}
La gestion des exceptions
Interception des exceptions
Il existe un gestionnaire particulier, catch(...) qui attrape tout type d'exception.
Ce gestionnaire ne peut se trouver qu'en dernire position (sinon, les
gestionnaires placs derrire lui n'attraperaient jamais rien).
int main() {

try {

...

catch (const char *s) { /*...*/ }

catch (int n) { /*...*/ }

catch (MonException &e) { /*...*/ }

catch (...) { std::cerr << "Exception inconnue"; }

return 0;

}
La gestion des exceptions
Utiliser les exceptions pour corriger
// Soit une classe Table(Y,X),
// avec une mthode de calcul :
double Table::interpole(double x) Les exceptions servent afficher des
{ messages d'erreur explicites :
// S'il y a sortie de table par
// excs on lve une exception
// avec le nom de la table, les catch (TableError &e)
{
// valeurs limites et la valeur
// qui dpasse : std::cerr<< "Sortie dans table : " << e.name<< "La
valeur " << e.x<< " dpasse la limite " << e.max_x;
throw TableError(name, max_y, max_x,
}
x);
}

Les exceptions ne sont pas seulement un bon moyen pour savoir quelle partie
du code a produit une erreur et pourquoi, elles permettent aussi de corriger
ces erreurs et de permettre au programme de continuer.
La gestion des exceptions
Utiliser les exceptions pour corriger
Voici un exemple de correction applique dans le cas dune sortie de table
dinterpolation. On dcide daccorder 5% de tolrance, mais au del, on lve
nouveau une exception :

try
{
coeffAxial = tabCoeffAxial.interpole(machNumber);
}
catch (TableError &e)
{
if (e.x < (1.05*e.max_x))
coeffAxial = e.max_y;
else
{
std::cerr << "Sortie de table " << e.name
<< " au dela des tolerances " << std::endl;
throw(e);
}
}
La gestion des exceptions
Spcifier l'exception
Il est possible de spcifier les exceptions quune fonction ou une mthode a le
droit de lever :
class X {};

class A {

void f1(); // nimporte quelle type exception

void f2() throw(); // ne peut lever dexception

void f3() throw(int); // peut lever des exceptions de type int

void f4() throw(int, double, X); // peut lever 3 types dexceptions

};

void g1();

void g2() throw(); Remarque:


Durant lexcution, si une exception dun type interdit est leve,
void g3() throw(int); le programme appelle une mthode spciale unexpected()
void g4() throw(int, double, X); que le programmeur peut par ailleurs modifier et utiliser
sa guise par set_unexpected().
La gestion des exceptions
Fichier en-tte <stdexcept> bibliothque standard fournissant des classes
dexceptions
Plusieurs exceptions standard susceptibles dtre dclenches par une
fonction ou un oprateur de la bibliothque standard
Ex. classe Bad_alloc en cas dchec dallocation mmoire par new
vect::vect (int n) // Constructeur de la classe vect

{ adr = new int [nelem = n] ;}

int main ()

{ try { vect v(-3) ; }

catch (bad_alloc) // Si le new sest mal pass

{ cout << "exception cration vect avec un mauvaise nombre d'lments " << endl ;

exit (-1) ;

}}
exception cration vect avec un mauvais
nombre d'lments

En cas dexception non gre appel automatique terminate()


La gestion des exceptions
Classe exception ayant une mthode virtuelle what() affichant une chane de
caractres expliquant lexception
int main ()
{
try { vect v(-3) ;}
catch (bad_alloc b)
{ // Appel de la mthode what() pour lexception bad_alloc
cout << b.what() << endl ; exit (-1) ; // affichage: St9bad_alloc
}
}
La gestion des exceptions
class exception {
public:
exception () throw();
exception (const exception&) throw();
exception& operator= (const exception&) throw();
virtual ~exception() throw();
virtual const char* what() const throw();
};
Classes drives de exception :
bad_alloc, bad_cast, bad_exception, bad_typeid
La gestion des exceptions
Possibilit de driver ses propres classes de la classe exception
class mon_exception : public exception

{ public :

mon_exception (char * texte) { ad_texte = texte ; }

const char * what() const throw() { return ad_texte ; }

private :

char ad_texte ;

};
La gestion des exceptions
int main()
{ try
{ cout << "bloc try 1" << endl;
throw mon_exception ("premier type") ; //construction la vole
}
catch (exception & e)
{ cout << "exception : " << e.what() << endl; }
try
Rsultat:
{ cout << "bloc try 2" << endl;
bloc try 1
throw mon_exception ("deuxieme type") ; exception : premier type
bloc try 2
} exception : deuxieme type
catch (exception & e)
{ cout << "exception : " << e.what() << endl;
}
}
La gestion des exceptions
Exceptions et constructeurs
Il est parfaitement lgal de lancer une exception dans un constructeur,
ce qui permettra de signaler une erreur lors de la construction dun
objet.
Lorsquune exception est lance partir dun constructeur, la
construction de lobjet choue. Par suite, le destructeur pour cet objet
ne sera pas appel, ce qui pose certains problmes si l'objet est
partiellement initialis.
La gestion des exceptions
Exemple:
L'exemple suivant montre comment traiter le cas des objets partiellement
initialiss, lorsque la cration de ces objets choue.
Considrons une classe "etudiant" qui permet de manipuler les notes d'un
tudiant.
Les notes de chaque tudiant seront stockes dans des tableaux d'entiers. On
suppose que le nombre de notes est variable et qu'il ne doit pas dpasser
une certaine valeur MAXNBNOTE.
On prvoit aussi dans cette classe une surcharge de l'oprateur [] qui permet
l'accs en lecture et en criture une note donne
Pour grer les diffrentes erreurs, on dfinit une classe de base "Erreur" et
deux autres classes DepMaxNbNote et InvalideIndice pour grer
respectivement le dpassement de nombre de notes autoris et le
dpassement d'indice.
La gestion des exceptions
#include <iostream>

#include <string>

#define MAXNBNOTE 4

#define MAXSIZE 255 class DepMaxNbNote:public erreur{


public:
using namespace std; //DepMaxNbNote():erreur(){}
//------ classes exception
DepMaxNbNote(const char *s):erreur(s){}
void affiche(){
class erreur{ erreur::affiche();
cout << "Nombre max de notes est " << MAXNBNOTE << endl;
protected: } };
const char * raison;

public:
class InvalideIndice:public erreur{
erreur():raison(0){} public:
erreur(const char* s):raison(s){} InvalideIndice():erreur(){}
InvalideIndice(const char *s):erreur(s){}
virtual void affiche(){ void affiche(int i){
erreur::affiche();
if (raison == NULL) cout << "Indice doit etre entre 0 et " << i << endl;
cout << "Erreur inconnu..." << endl; }
};
else cout << raison << endl;

} };
La gestion des exceptions
//--------- classe etudiant //------------ constructeur
etudiant::etudiant(char* nom, int nbnotes)
class etudiant{ {
try
char * _nom; // nom
{
int _nbnotes; // nombre de notes _nom = new char[strlen(nom)+1];
strcpy(_nom,nom);
int * tabnotes; // tableau de notes if( (nbnotes < 0) || (nbnotes > MAXNBNOTE) ){
DepMaxNbNote err("Erreur dans Constructeur");
public: throw err;
}
etudiant(char*,int); _nbnotes = nbnotes;
~etudiant(); tabnotes = new int[nbnotes];
}
int GetNbNotes(){ return _nbnotes;} catch(DepMaxNbNote & err)
{
int & operator[](int); delete _nom;
err.affiche();
void affiche(); exit(-1);
}
};
}
La STL (standard template library)
La STL fournit entre autre:
des classes pour les structures de donnes classiques
structures squentielles : vector, list,
structures associative : (multi)set, (multi)map
des itrateurs offrant une interface uniforme pour manipuler ces
structures
des algorithmes varis sur ces structures

Un lien utile : http://www.sgi.com/tech/stl/


La STL (standard template library)
Les containers
Les containers sont des objets qui permettent de stocker dautres objets. Ils sont
dcrits par des classes gnriques reprsentant les structures de donnes
logiques les plus couramment utilises : les listes, les tableaux, les
ensembles... Ces classes sont dotes de mthodes permettant de crer, de
copier, de dtruire ces containers, dy insrer, de rechercher ou de supprimer
des lments. La gestion de la mmoire, cest--dire lallocation et la
libration de la mmoire, est contrle directement par les containers, ce qui
facilite leur utilisation.
La STL (standard template library)
containers disponibles:
vector : container implantant les tableaux, qui autorise les accs directs sur ses
lments. Les oprations de mise jour (insertion, suppression) sont ralises en un
temps constant la fin du container, et en un temps linaire (dpendant du nombre
dlments) aux autres endroits.
list : container implantant les listes doublement chanes, ddi la reprsentation
squentielle de donnes. Les oprations de mise jour sont effectues en un temps
constant nimporte quel endroit du container.
deque : container similaire au vector, effectuant de plus les oprations de mise jour
en dbut de container en un temps constant.
set : container implantant les ensembles o les lments ne peuvent tre prsents au
plus quen unseul exemplaire.
multiset : container implantant les ensembles o les lments peuvent tre prsents
en plusieurs exemplaires.
map : container implantant des ensembles o un type de donnes appel cl est
associ aux lments stocker. On ne peut associer quune seule valeur une cl
unique. On appelle aussi ce type de container tableau associatif.
La STL (standard template library)
multimap : container similaire au map supportant lassociation de
plusieurs valeurs une cl unique.
stack : container implantant les piles, qui sont des listes spciales, dites
LIFO.
queue : container implantant les files, qui sont des listes spciales, dites
FIFO.
Exemple
#include <iostream>
#include <vector>
#include <list>
// Nombre dlments des containers
int main() cout << "Il y a" << tableauEntiers.size()
{ << " lments dans le tableau" << endl;
vector<int> tableauEntiers; // Cre un tableau dentiers vide cout << "Il a y " << listeEntiers.size()
list<int> listeEntiers; // Cre une liste dentiers vide << " lments dans la liste" << endl; // Accs des lments
int unEntier; cout << "Premier lment du tableau : "
// Saisie des entiers << tableauEntiers.front() << endl;
cout << "Saisir le prochain entier (-1 pour finir) : "; cout << "Premier lment de la liste : "
cin >> unEntier; << listeEntiers.front() << endl;
while (unEntier != -1) { int milieu = tableauEntiers.size() / 2;
tableauEntiers.push_back(unEntier); cout << "lment de milieu de tableau : "
listeEntiers.push_back(unEntier); << tableauEntiers[milieu] << endl;
cout << "Saisir le prochain entier (-1 pour finir) : ";
}
cin >> unEntier;}
Saisir le prochain entier (-1 pour finir) : 4
Saisir le prochain entier (-1 pour finir) : 5
Saisir le prochain entier (-1 pour finir) : 3
Saisir le prochain entier (-1 pour finir) : 7
Saisir le prochain entier (-1 pour finir) : 6
Saisir le prochain entier (-1 pour finir) : 3
Saisir le prochain entier (-1 pour finir) : -1
Il a y 6 lments dans le tableau
Il a y 6 lments dans la liste
Premier lment du tableau : 4
Premier lment de la liste : 4
lment de milieu de tableau : 7
La STL (standard template library)
Les Itrateurs ( Iterators)
Les itrateurs sont une gnralisation des pointeurs, ce qui permet
au programmeur de travailler avec des containers diffrents de faon
uniforme.
Ils permettent de spcifier une position lintrieur dun container,
Peuvent tre incrments ou drfrencs ( la manire des
pointeurs utiliss avec loprateur de drfrencement *),
Deux itrateurs peuvent tre compars.
Tous les containers sont dots dune mthode begin qui renvoie un
itrateur sur le premier de leurs lments, et dune mthode end qui
renvoie un itrateur sur une place se trouvant juste aprs le dernier
de leurs lments.
On ne peut pas ainsi drfrencer litrateur renvoy par la mthode
end.
La STL (standard template library)
Exemple
#include <iostream>
#include <list>
int main()
{
list<int> lesEntiers;
// Ici, des instructions pour initialiser la liste des entiers

// Affichage des lments contenus dans la liste


list<int>::iterator it;
for (it = lesEntiers.begin(); it != lesEntiers.end(); it++)
cout << *it << endl;
}
La STL (standard template library)
Iterator (suite)
Un itrateur :
pointe sur un lment dun conteneur
peut tre incrment par ++
peut tre drfrenc par *

Il y a 3 types d'itrateurs :
unidirectionnel
bidirectionnel (--)
accs direct (it + i, it[i])

Remarque:
Itrateur de fin pointe juste aprs le dernier lment du conteneur
Si la liste vide : li.begin() possde la mme valeur que li.end()
La STL (standard template library)
Les algorithmes
Les algorithmes sont des fonctions C++ gnriques qui permettent
deffectuer des oprations sur les containers.
Afin de pouvoir sappliquer plusieurs types de containers, les
algorithmes ne prennent pas de containers en arguments, mais des
itrateurs qui permettent de dsigner une partie ou tout un container.
De ce fait, il est mme possible dutiliser ces algorithmes sur des
objets qui ne sont pas des containers.
Certains algorithmes ne ncessitent que des itrateurs de base
(dentre ou de sortie), et dautres ncessitent des itrateurs plus
volus, comme la fonction sort (effectuant un tri) qui ncessite un
itrateur accs direct.
La STL (standard template library)
Exemple
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
vector<int> tableauEntiers; // Cre un tableau dentiers vide
int unEntier;
// Saisie des entiers

// Tri du tableau
sort(tableauEntiers.begin(), tableauEntiers.end());
// Affichage des lments tris
vector<int>::iterator it;
for (it = tableauEntiers.begin(); it != tableauEntiers.end(); it++)
cout << *it ;
}

You might also like