You are on page 1of 18

Programmation en langage C++

Concepts
par Claude DELANNOY
Ingnieur de lENSEM (cole nationale suprieure dlectricit
et de mcanique) de Nancy
Ingnieur informaticien au CNRS (Centre national de la recherche scientifique)

1. Prsentation gnrale............................................................................. S 8 065 2


2. Amliorations de C++ par rapport C ............................................... 3
3. Notion de classe....................................................................................... 5
4. Fonctions amies ....................................................................................... 8
5. Surdfinition doprateurs .................................................................... 8
6. Hritage ...................................................................................................... 9
7. Fonctions virtuelles et polymorphisme ............................................. 12
8. Flots dentre et de sortie ..................................................................... 12
9. Patrons de fonctions............................................................................... 13
10. Patrons de classes ................................................................................... 14
11. Gestion des exceptions .......................................................................... 16
12. Bibliothque standard ............................................................................ 16
Rfrences bibliographiques ......................................................................... 18

a programmation oriente objet (en abrg POO) est dornavant universelle-


L ment reconnue pour les avantages quelle procure. Notamment, elle am-
liore largement la productivit des dveloppeurs, la robustesse, la portabilit et
lextensibilit de leurs programmes. Enfin, et surtout, elle permet de dvelopper
des composants logiciels entirement rutilisables.
Un certain nombre de langages dits langages orients objet (LOO) ont t
dfinis de toutes pices pour appliquer les concepts de POO. Cest ainsi que sont
apparus dans un premier temps des langages comme Smalltalk, Simula ou Eiffel
puis, plus rcemment, Java. Le langage C++, quant lui, a t conu suivant une
dmarche quelque peu diffrente par B. Stroustrup (AT&T) ; son objectif a t, en
effet, d'adjoindre au langage C un certain nombre de spcificits lui permettant
d'appliquer les concepts de POO. Ainsi, C++ prsente-t-il sur un vrai LOO l'origi-
nalit d'tre fond sur un langage rpandu. Cela laisse au programmeur toute
libert d'adopter un style plus ou moins orient objet, en se situant entre les
deux extrmes que constituent la poursuite d'une programmation classique
d'une part, une pure POO d'autre part. Si une telle libert prsente le risque de
cder, dans un premier temps, la facilit en mlangeant les genres (la POO ne
renie pas la programmation classique - elle l'enrichit), elle permet galement
une transition en douceur vers la POO pure, avec tout le bnfice que l'on peut
en escompter terme.
De sa conception jusqu' sa normalisation, le langage C++ a quelque peu vo-
lu. Initialement, un certain nombre de publications de AT&T ont servi de rf-
rence au langage. Les dernires en date sont : la version 2.0 en 1989, les versions
2.1 et 3 en 1991. Cest cette dernire qui a servi de base au travail du comit ANSI
(American National Standard Institute) lequel, sans la remettre en cause, l'a enri-

Toute reproduction sans autorisation du Centre franais dexploitation du droit de copie est strictement interdite.
Techniques de lIngnieur, trait Informatique industrielle S 8 065 1
PROGRAMMATION EN LANGAGE C++ ______________________________________________________________________________________________________

chie de quelques extensions et surtout de composants standards originaux se


prsentant sous forme de fonctions et de classes gnriques que lon dsigne
souvent par le sigle STL (Standard Template Library). La norme dfinitive de C++
a t publie en juillet 1998.
Cet article est extrait de louvrage Programmer en langage C++ du mme
auteur, paru aux ditions Eyrolles [5].

1. Prsentation gnrale drablement la maintenance : une modification ventuelle de la


structure des donnes dun objet na dincidence que sur lobjet lui-
mme ; les utilisateurs de lobjet ne seront pas concerns par la
teneur de cette modification (ce qui ntait bien sr pas le cas avec
Afin de mieux situer le langage C++, nous commencerons par la programmation structure). De la mme manire, lencapsulation
quelques rappels concernant la POO. des donnes facilite grandement la rutilisation dun objet.

1.1 Programmation oriente objet 1.1.3 Classe

En POO apparat gnralement le concept de classe, qui corres-


1.1.1 De la programmation structure la POO pond la gnralisation de la notion de type que lon rencontre
dans les langages classiques. En effet, une classe nest rien dautre
Si lactivit de programmation peut savrer simple lorsquil sagit que la description dun ensemble dobjets ayant une structure de
de dvelopper un code de quelques lignes, elle peut devenir extr- donnes commune et disposant des mmes mthodes. Les objets
mement complexe lorsque la taille des programmes devient impor- apparaissent alors comme des variables dun tel type classe (en
tante. La production industrielle de logiciel doit alors chercher POO, on dit aussi quun objet est une instance de sa classe).
imposer des exigences de qualit et tenter de les mesurer en utili-
sant certains critres comme lexactitude, la robustesse, lextensibi-
lit, la rutilisabilit, la portabilit, lefficience.
1.1.4 Hritage
La programmation structure a, en son temps, permis de faire Un autre concept important en POO est celui dhritage. Il permet
progresser la qualit de la production des logiciels. Elle reposait sur de dfinir une nouvelle classe partir dune classe existante (que
ce que lon nomme souvent lquation de Wirth , savoir : lon rutilise en bloc !), laquelle on ajoute de nouvelles donnes et
Procdures + Structures de donnes = Programmes de nouvelles mthodes. La conception de la nouvelle classe, qui
hrite des proprits et des aptitudes de lancienne, peut ainsi
Bien sr, elle a permis de structurer les programmes, et partant,
sappuyer sur des ralisations antrieures parfaitement au point et
den amliorer lexactitude et la robustesse. En revanche, elle na
les spcialiser volont. Comme on peut sen douter, lhritage
pas tenu ses promesses pour ce qui est de ladaptation ou la rutili-
facilite largement la rutilisation de produits existants, dautant plus
sation des programmes. Ces oprations obligeaient gnralement
quil peut tre ritr autant de fois que ncessaire (la classe C peut
remettre en cause une structure de donnes et donc modifier une
hriter de B, qui elle-mme hrite de A).
ou plusieurs des procdures agissant sur elle. Ce type de difficults
mane directement de lquation de Wirth, qui dcouple totalement
les donnes des procdures agissant sur ces donnes.
Cest l quintervient la programmation oriente objet (en abrg 1.2 Place de C++ par rapport C
POO), fonde justement sur le concept dobjet, savoir une associa-
tion des donnes et des procdures (que lon appelle alors mtho- On peut dire que C++ se prsente comme une extension du lan-
des) agissant sur ces donnes. Par analogie avec lquation de gage C offrant des possibilits de POO.
Wirth, on pourrait dire que lquation de la POO est :
Mais tous les apports du C++ par rapport au C ne sont pas lis la
Mthodes + Donnes = Objet POO. Certains pourraient en effet tre ajouts avec profit au C, sans
quil devienne pour autant orient objet. Cela est notamment le cas
1.1.2 Encapsulation pour la notion de rfrence et pour les surdfinitions de fonctions
que nous examinerons au paragraphe 2.
Mais cette association est plus quune simple juxtaposition. En Les possibilits de POO reprsentent bien sr lessentiel des
effet, elle sassortit de ce que lon nomme une encapsulation des apports de C++. On y retrouve tout naturellement les notions de
donnes. Cela signifie quil nest pas possible dagir directement sur classe, dencapsulation et dhritage, voques prcdemment.
les donnes dun objet ; il est ncessaire de passer par linterm- Mais le programmeur nest pas tenu dy recourir tout prix comme
diaire de ses mthodes, qui jouent ainsi le rle dinterface obliga- il devrait le faire dans un pur langage orient objet. Ainsi, pourra-t-il
toire. On traduit parfois cela en disant que lappel dune mthode est crer un programme sans utiliser de classes, ou encore crer des
en fait lenvoi dun message lobjet. classes sans respecter totalement le principe dencapsulation...
Le grand mrite de lencapsulation est que, vu de lextrieur, un Par ailleurs, C++ se trouve dot de fonctionnalits POO originales
objet se caractrise uniquement par les spcifications (noms, argu- dont ne disposent pas tous les langages orients objet :
ments et rle) de ses mthodes, la manire dont sont rellement comme en Java, une classe peut tre munie de constructeur
implantes les donnes tant sans importance. On dcrit souvent (mthode obligatoirement excute lors de toute cration dun
une telle situation en disant quelle ralise une abstraction des objet) et de destructeur (mthode excute au moment de la des-
donnes , ce qui exprime bien que les dtails concrets dimpl- truction dun objet) ;
mentation sont cachs. Lencapsulation des donnes prsente un on peut dfinir des fonctions amies dune classe . Il sagit de
intrt manifeste en matire de qualit de logiciel. Elle facilite consi- fonctions usuelles (qui ne sont donc pas des mthodes dune

Toute reproduction sans autorisation du Centre franais dexploitation du droit de copie est strictement interdite.
S 8 065 2 Techniques de lIngnieur, trait Informatique industrielle
______________________________________________________________________________________________________ PROGRAMMATION EN LANGAGE C++

classe) qui sont autorises (par une classe) accder aux donnes namespace une_bibli
(encapsules) de la classe ; { // dclarations usuelles
la surdfinition doprateurs permet de doter une classe
}
doprations analogues celles que lon rencontre pour les types
prdfinis. Par exemple, on pourra dfinir une classe nomme Pour se rfrer des identificateurs dfinis dans cet espace de
complexe (destine reprsenter des nombres complexes) et la noms, on utilisera une instruction using :
munir des oprations daddition, de soustraction, de multiplication using namespace une_bibli
et de division. Qui plus est, ces oprations pourront utiliser les sym- // ici, les identificateurs de une_bibli sont connus
boles existants : +, -, *, / ;
les entres-sorties deviennent fondes sur la notion de flot , On peut aussi utiliser l'instruction using pour faire un choix per-
ce qui permet de leur donner un sens pour les types dfinis par luti- manent :
lisateur que sont les classes (grce au mcanisme de surdfinition using une_bibli::point ; // dornavant, l'identificateur point,
doprateur) ; // employ seul correspondra celui
la notion de patron permet de dfinir des modles utilisables // dfini dans l'espace de noms une_bibli
pour gnrer diffrentes classes ou diffrentes fonctions qualifies
parfois de gnriques, mme si cette gnricit nest pas totalement Tous les identificateurs des fichiers en-tte standards sont dfinis
intgre dans le langage lui-mme, comme cest par exemple le cas dans lespace de noms std ; aussi est-il ncessaire de recourir syst-
avec ADA ; matiquement linstruction :
dans la bibliothque standard de C++, qui vient complter using namespace std ; // utilisation des fichiers
celle du C, toujours disponible, on trouve de nombreux patrons de // en-tte standard //
classes et de fonctions permettant de mettre en uvre les structures
de donnes et les algorithmes les plus usuels, vitant ainsi davoir Gnralement, cette instruction figurera un niveau global. Elle
rinventer la roue la moindre occasion. ne peut cependant apparatre que si lespace de noms quelle men-
tionne existe dj ; en pratique, cela signifie que cette instruction
sera place aprs linclusion des fichiers en-tte.

2. Amliorations de C++
par rapport C 2.3 Nouvelles possibilits
d'entres-sorties
Nous dcrivons ici les principales amliorations non orientes
objet que C++ a apport au langage C. C++ dispose de nouvelles facilits d'entres-sorties. Bien qu'elles
soient fortement lies des aspects POO (surdfinition d'oprateur
en particulier), elles sont parfaitement utilisables en dehors de ce
2.1 Scurisation de lutilisation contexte. C'est tout particulirement le cas des possibilits
des fonctions d'entres-sorties conversationnelles (clavier, cran) qui remplacent
avantageusement les fonctions printf et scanf. Ainsi :

Le langage C est laxiste en matire de dclaration de fonctions. En cout << expression_1 << expression_2 << ......... << expression_n
effet, sil permet deffectuer des dclarations compltes (prototype affiche sur le flot cout (connect par dfaut la sortie standard
avec type des arguments et de la valeur de retour), il autorise gale- stdout) les valeurs des diffrentes expressions indiques, suivant
ment des dclarations partielles, voire mme dans certains cas une une prsentation adapte leur type. De mme :
absence totale de dclaration.
C++ ne conserve que laspect le plus fiable de C, tel quil tait dj cin >> variable_1 >> variable_2 >> ......... >> variable_n
utilis par les programmeurs C soucieux de scuriser leurs pro- lit sur le flot cin (connect par dfaut l'entre standard stdin) des
grammes. Il impose que toute fonction utilise dans un fichier informations de l'un des types char, short, int, long, float, double ou
source fasse lobjet : char * (les pointeurs ne sont pas admis). Les conventions d'analyse
soit d'une dclaration sous forme d'un prototype (il prcise des caractres lus sont comparables celles de scanf, avec cette
la fois le nom de la fonction, le type de ses arguments ventuels et principale diffrence que la lecture d'un caractre commence par
le type de sa valeur de retour), comme dans cet exemple : sauter les espaces blancs (espace, tabulation horizontale, tabulation
float fexp (int, double, char *) ; verticale, fin de ligne, changement de page).

soit d'une dfinition pralable au sein du mme fichier source


(ce dernier cas tant d'ailleurs peu conseill, dans la mesure o des Ces nouvelles possibilits d'entres-sorties ncessitent
problmes risquent d'apparatre si, par la suite, on spare ladite l'inclusion d'un fichier en-tte nomm iostream. Compte tenu
fonction du fichier source en question). de la notion despace de noms examine ci-avant, on voit quil
est gnralement ncessaire de faire prcder tout fichier
source de ces instructions :
2.2 Espaces de noms #include <iostream>
using namespace std ;
Lorsque l'on doit utiliser plusieurs bibliothques dans un pro-
gramme, on peut tre confront au problme dit de pollution de
lespace des noms , li ce qu'un mme identificateur peut trs
bien avoir t utilis par plusieurs bibliothques. Le mme pro- 2.4 Nouvelle forme de commentaires
blme peut se poser, un degr moindre toutefois, lors du dvelop-
pement de gros programmes. C'est la raison pour laquelle la norme
ANSI du C++ a introduit le concept d espace de noms . Il s'agit En C, un commentaire peut tre introduit en n'importe quel
simplement de donner un nom un espace de dclarations, en endroit o un espace est autoris en le faisant prcder de /* et sui-
procdant ainsi : vre de */. Il peut alors ventuellement s'tendre sur plusieurs lignes.

Toute reproduction sans autorisation du Centre franais dexploitation du droit de copie est strictement interdite.
Techniques de lIngnieur, trait Informatique industrielle S 8 065 3
PROGRAMMATION EN LANGAGE C++ ______________________________________________________________________________________________________

En C++, vous pouvez en outre utiliser des commentaires de fin Exemple : utilisation de la transmission d'arguments par rf-
de ligne en introduisant les deux caractres : //. Dans ce cas, tout rence en C++
ce qui est situ entre // et la fin de la ligne est un commentaire. Notez
que cette nouvelle possibilit n'apporte qu'un surcrot de confort et #include <iostream>
de scurit ; en effet, une ligne telle que : using namespace std ;
main()
cout << "bonjour\n" ; // formule de politesse { void echange (int &, int &) ;
peut toujours tre crite ainsi : int n=10, p=20 ;
cout << "avant appel : " << n << " " << p << "\n" ;
cout << "bonjour\n" ; /*formule de politesse*/
echange (n, p) ; // attention, ici pas de &n, &p
Vous pouvez mler (volontairement ou non !) les deux formules. cout << "apres appel : " << n << " " << p << "\n" ;
Dans ce cas, notez que, dans : }
/* partie1 // partie2 */ partie3 void echange (int & a, int & b)
{ int c ;
le commentaire ouvert par /* ne se termine qu'au prochain */ ; cout << "debut echange : " << a << " " << b << "\n" ;
donc partie1 et partie2 sont des commentaires, tandis que partie3 c=a;a=b;b=c;
est considr comme appartenant aux instructions. De mme, dans : cout << "fin echange : " << a << " " << b << "\n" ;
partie1 // partie2 /* partie3 */ partie4 }
le commentaire introduit par // stend jusqu la fin de la ligne. Il ________________________________
concerne donc partie2, partie3 et partie4.
avant appel : 10 20
dbut echange : 10 20
fin echange : 20 10
2.5 Transmission par rfrence aprs appel : 20 10

Cette fois, lutilisateur de la fonction echange na plus se soucier


En C, il nexiste quun seul mode de transmission des arguments de la manire de lappeler.
et de la valeur de retour dune fonction, savoir par valeur . Il
reste cependant possible de simuler en quelque sorte ce qui se
nomme transmission par rfrence (ou par adresse) dans
d'autres langages, moyennant lutilisation de pointeurs : la trans- 2.6 Arguments par dfaut
mission se fait toujours par valeur mais, dans ce cas, il s'agit de la
valeur d'un pointeur. En voici un exemple (crit ici en C++) dans
lequel une fonction nomme echange ralise lchange du contenu Dans la dclaration d'une fonction (prototype), il est possible de
de deux variables. prvoir pour un ou plusieurs arguments (obligatoirement les der-
niers de la liste) des valeurs par dfaut ; elles sont indiques par le
Exemple : mise en uvre par le programmeur d'une transmis- signe =, la suite du type de l'argument comme dans cet exemple :
sion par adresse
float fct (char, int = 10, float = 0.0) ;
#include <iostream> Ces valeurs par dfaut seront alors utilises lorsque l'on appellera
using namespace std ; ladite fonction avec un nombre d'arguments infrieur celui prvu.
main() Par exemple, avec la prcdente dclaration, l'appel fct ('a') sera
{ void echange (int *, int *) ; quivalent fct ('a', 10, 0.0) ; de mme, l'appel fct ('x', 12) sera qui-
int n=10, p=20 ; valent fct ('x', 12, 0.0). En revanche, l'appel fct () sera illgal.
cout << "avant appel : " << n << " " << p << "\n" ;
echange (&n, &p) ;
cout << "apres appel : " << n << " " << p << "\n" ;
} 2.7 Surdfinition de fonctions
void echange (int *a, int *b) // a et b sont des pointeurs
{ int c ;
cout << "debut echange : " << * a << " " << * b << "\n" ; En C++, il est possible, au sein d'un mme programme, que plu-
c = *a ; *a = *b ; *b = c ; // on change les valeurs pointes sieurs fonctions possdent le mme nom. Dans ce cas, lorsque le
cout << "fin echange : " << * a << " " << * b << "\n" ; compilateur rencontre l'appel d'une telle fonction, il effectue le
} choix de la bonne fonction en tenant compte de la nature des
arguments effectifs comme dans cet exemple.
____________________________
void sosie (int) ; // sosie I
avant appel : 10 20 void sosie (double) ; // sosie II
debut echange : 10 20 int n ; double y ;
fin echange : 20 10 .....
apres appel : 20 10 sosie (n) ; // appelle sosie I
sosie (y) ; // appelle sosie II
On voit quici, le programmeur doit connatre la technique utilise
par la fonction echange afin de lui transmettre en argument, non Le compilateur peut aussi tenir compte du nombre des arguments
pas les variables elles-mmes, mais bel et bien des pointeurs sur comme dans cet exemple.
ces variables.
En C++, en faisant suivre du symbole & le type dun argument void sosie (int) ; // sosie I
dans len-tte (et dans le prototype), on ralise une vritable trans- void sosie (int, double) ; // sosie II
mission par rfrence. Cela signifie que les ventuelles modifica- int n ; double y ;
tions effectues au sein de la fonction porteront sur largument .....
effectif de lappel et non plus sur une copie. Voici comment pourrait sosie (n) ; // appelle sosie I
se programmer lexemple prcdent. sosie (n, y) ; // appelle sosie II

Toute reproduction sans autorisation du Centre franais dexploitation du droit de copie est strictement interdite.
S 8 065 4 Techniques de lIngnieur, trait Informatique industrielle
______________________________________________________________________________________________________ PROGRAMMATION EN LANGAGE C++

Il peut galement mettre en place des conversions implicites. membres donnes privs x et y et trois fonctions membres publi-
ques initialise, deplace et affiche :
void sosie (int) ; // sosie I /* ------- Dclaration de la classe point -------- */
void sosie (double) ; // sosie II class point
char c ; float y ; { /* dclaration des membres privs */
..... private :
sosie(c) ; // appelle sosie I, aprs conversion de c en int int x ;
sosie(y) ; // appelle sosie II, aprs conversion de y en double int y ;
/* dclaration des membres publics */
Dune manire gnrale, il existe des rgles trs prcises (trop public :
complexes pour tre cites ici) que le compilateur utilise dans sa void initialise (int, int) ; // initialise les coordonnes
recherche de la bonne fonction. void deplace (int, int) ; // modifie les coordonnes
void affiche () ; // affiche les coordonnes
};
La dfinition d'une classe consiste fournir les dfinitions des
2.8 Gestion dynamique de la mmoire fonctions membre. On indique alors le nom de la classe correspon-
dante, l'aide de l'oprateur de rsolution de porte (::). Au sein de
la dfinition mme, les membres (privs ou publics donnes ou
Comme en C, les emplacement allous aux variables (ou aux fonctions) sont directement accessibles sans qu'il soit ncessaire de
objets) se classent en trois catgories, suivant la faon sont ils sont prciser le nom de la classe. Voici, par exemple, ce que pourrait tre
allous : la dfinition de la fonction initialise de la classe prcdente.
automatique : les emplacements sont allous lentre dans void point::initialise (int abs, int ord)
une fonction, et librs sa sortie ; il en va ainsi pour les arguments { x = abs ; y = ord ;
dune fonction et pour les variables locales ; }
statique : les emplacements sont allous une fois pour toute void point::deplace (int dx, int dy)
avant le dbut de lexcution ; { x = x + dx ; y = y + dy ;
dynamique : les emplacements sont allous lors de lexcu- }
tion, sur demande explicite du programme ; il en va de mme pour void point::affiche ()
leur libration. { cout << "Je suis en " << x << " " << y << "\n" ;
}
Mais, alors que la gestion dynamique en C recourait aux fonctions
malloc et calloc, il est conseill en C++ dutiliser les oprateurs new Ici, x et y reprsentent implicitement les membres x et y d'un
et delete. Plus prcisment, si T reprsente un type quelconque objet de la classe point.
(ventuellement classe), avec :
T * ad ;
ad = new T ;
3.2 Utilisation d'une classe
on alloue lemplacement ncessaire pour un emplacement de type On dclare un objet d'un type classe donn en faisant prc-
T et on affecte ad ladresse correspondante. der son nom de celui de la classe, comme dans l'instruction sui-
Avec : vante qui dclare deux objets a et b de type point :
point a, b ;
delete ad ;
On peut accder n'importe quel membre public (donne ou
on libre lemplacement prcdemment allou. fonction) d'une classe en utilisant l'oprateur . (point). Par exemple :
a.initialise (5, 2) ;
appelle la fonction membre initialise de la classe laquelle appar-
3. Notion de classe tient lobjet a, c'est--dire, ici, la classe point.

3.3 Affectation entre objets


Une classe est donc la gnralisation de la notion de type dfini
par l'utilisateur, dans lequel se trouvent associes la fois des don- C++ autorise l'affectation d'un objet d'un type donn un autre
nes (on parle en C++ de membres donnes ) et des mthodes objet de mme type comme dans cet exemple utilisant la classe
(on parle de fonctions membres ). En POO pure, les donnes sont point prcdente :
encapsules , ce qui signifie que leur accs ne peut se faire que
par le biais des mthodes. C++ vous autorise n'encapsuler qu'une point a, b ;
partie seulement des donnes d'une classe. .....
b=a;
Dans ce cas, il y a (tout naturellement) recopie des valeurs des
3.1 Dclaration et dfinition d'une classe champs de donnes qu'ils soient publics ou privs. Ainsi, ici, les
valeurs de a.x et a.y sont-elles recopies dans les champs b.x et b.y,
bien que ces derniers soient privs.
La dclaration d'une classe prcise quels sont les membres (don- Toutefois, si, parmi les champs ainsi recopis, se trouvent des
nes ou fonctions) publics (c'est--dire accessibles l'utilisateur de pointeurs, les emplacements points ne seront pas soumis cette
la classe) et quels sont les membres privs (inaccessibles l'utilisa- recopie. Si un tel effet est ncessaire (et il le sera souvent !), il ne
teur de la classe). On utilise pour cela les mots cls public et private, pourra tre obtenu qu'en surdfinissant l'oprateur d'affectation
comme dans cet exemple dans lequel la classe point comporte deux pour la classe concerne.

Toute reproduction sans autorisation du Centre franais dexploitation du droit de copie est strictement interdite.
Techniques de lIngnieur, trait Informatique industrielle S 8 065 5
PROGRAMMATION EN LANGAGE C++ ______________________________________________________________________________________________________

3.4 Constructeur et destructeur 3.6 Exploitation dune classe

Une fonction membre portant le mme nom que sa classe se Lexemple prcdent tait form dun seul fichier source conte-
nomme un constructeur. Ds qu'une classe comporte un construc- nant la fois la dclaration de la classe, sa dfinition et son utilisa-
teur, il n'est plus possible de dclarer un objet du type corres- tion. En pratique, on aura gnralement intrt placer chaque
pondant, sans fournir des valeurs pour les arguments requis par ce partie dans un fichier source diffrent, de manire permettre dif-
constructeur (sauf si ce dernier ne possde aucun argument). Le frents programmes dutiliser une mme classe.
constructeur est appel aprs l'allocation de l'espace mmoire des- Dans ces conditions, on pourra compiler la dfinition de la classe
tin lobjet (quelle que soit la classe dallocation correspondante - (une fois pour toutes) et fournir tout utilisateur potentiel le module
automatique, dynamique ou statique). objet correspondant accompagn dun fichier en-tte contenant la
Par dfinition, un constructeur ne renvoie pas de valeur (aucune dclaration de la classe.
indication de type, pas mme void, ne doit figurer devant sa dcla-
ration ou sa dfinition).
Une fonction membre portant le mme nom que sa classe, pr- 3.7 Membres donnes statiques
cd du symbole tilde (~), se nomme un destructeur. Le destructeur
est appel avant la libration de l'espace mmoire associ l'objet.
Par dfinition, un destructeur ne peut pas comporter d'arguments et Un membre donne dclar avec l'attribut static est partag par
il ne renvoie pas de valeur (aucune indication de type ne doit tre tous les objets de la mme classe. Il existe mme lorsque aucun
prvue). objet de cette classe n'a t dclar. Un membre donne statique
doit tre initialis explicitement, l'extrieur de la classe (mme s'il
est priv), en utilisant l'oprateur de rsolution de porte (::) pour
spcifier sa classe. En gnral, son initialisation se fait dans la dfi-
3.5 Exemple complet nition de la classe.

Voici un exemple complet regroupant la dclaration, la dfinition 3.8 Surdfinition des fonctions membres
et lutilisation dune classe point. Notez que la mthode initialise
prcdente a t avantageusement remplace par un constructeur. et arguments par dfaut
Exemple : dclaration, dfinition et utilisation dune classe Il s'agit simplement de la gnralisation aux fonctions membres
/* -------- Dclaration de la classe point --------- */ des possibilits dj offertes par C++ pour les fonctions
class point ordinaires . Voici par exemple une classe point surdfinissant
{ /* dclaration des membres publics */ trois constructeurs et disposant dune fonction affiche possdant un
public : argument par dfaut.
point (int, int) ; // constructeur
class point
void deplace (int, int) ;
{ public :
void affiche () ;
point () ; // constr 1 (sans argument)
/* dclaration des membres privs */
point (int) ; // constr 2 (un argument)
int x ;
point (int, int) ; // constr 3 (deux arguments)
int y ;
void affiche (char * = "") ; // un argument par dfaut
};
private :
/* --- Dfinition des fonctions membre de la classe point -- */ int x, y ;
point::point (int abs, int ord) };
{ x = abs ; y = ord ; point::point () // constructeur 1
} { x=0;y=0;
void point::deplace (int dx, int dy) }
{ x = x + dx ; y = y + dy ; point::point (int abs) // constructeur 2
} { x = y = abs ;
void point::affiche () }
{ cout << "Je suis en " << x << " " << y << "\n" ; point::point (int abs, int ord) // constructeur 3
} { x = abs ; y = ord ;
}
/* -------- Utilisation de la classe point -------- */ void point::affiche (char * message)
main() { cout << message << "Je suis en : " << x << " " << y << "\n" ;
{ point a(5,2) ; }
a.affiche () ;
a.deplace (-2, 4) ; a.affiche () ; En voici quelques exemples dutilisation.
point b(1,-1) ;
b.affiche () ; point a ; // appel constructeur 1
b=a; point b (5) ; // appel constructeur 2
b.affiche () ; point c (3, 12) ; // appel constructeur 3
} .....
______________________ a.affiche () ;
// affiche : Je suis en : 0 0
Je suis en 5 2 b.affiche ("Point b - ") ;
Je suis en 3 6 // affiche : Point b - Je suis en : 5 5
Je suis en 1 -1 c.affiche ("Hello ---- ") ;
Je suis en 3 6 // affiche : Hello ---- Je suis en : 3 12

Toute reproduction sans autorisation du Centre franais dexploitation du droit de copie est strictement interdite.
S 8 065 6 Techniques de lIngnieur, trait Informatique industrielle
______________________________________________________________________________________________________ PROGRAMMATION EN LANGAGE C++

3.9 Cas des objets transmis en arguments point * adp ;


d'une fonction membre .....
adp = new point (2, 5) ; // cration d'un objet de type point, par
Une fonction membre agit automatiquement sur lobjet layant // appel d'un constructeur
appel sans quil ne soit ncessaire de lui en fournir explicitement // deux arguments
ladresse (transmise en fait implicitement par le compilateur). Mais, L'accs aux membres d'un objet dynamique est ralis comme
en outre, il est toujours possible de lui transmettre explicitement un pour les variables ordinaires. Par exemple, si point possde une
argument (ou plusieurs) du type de sa classe, ou mme du type mthode nomme affiche, on pourra lappeler par (*adp).affiche ()
d'une autre classe. Dans le premier cas, la fonction membre aura ou encore par adp->affiche ().
accs aux membres privs de l'argument en question (car, en C++,
l'unit d'encapsulation est la classe elle-mme et non lobjet). En Comme les variables dynamiques, les objets dynamiques n'ont
revanche, dans le second cas, la fonction membre n'aura accs pas de dure de vie dfinie a priori. Ils sont dtruits la demande en
qu'aux membres publics de l'argument. utilisant l'oprateur delete comme dans : delete adr.
Un tel argument peut tre transmis classiquement par valeur, par
adresse ou par rfrence. Avec la transmission par valeur, il y a reco-
pie des valeurs des membres donnes dans un emplacement local 3.13 Construction d'objets contenant
la fonction appele. Des problmes peuvent surgir ds lors que des objets membres
lobjet transmis en argument contient des pointeurs sur des parties
dynamiques. Ils devront tre rgls par l'emploi d'un constructeur Une classe peut possder un membre donne qui soit lui-mme
par recopie . de type classe. En voici un exemple. Si nous avons dfini :
Voici comment nous pourrions dfinir dans une des classes point class point
prcdente, une fonction membre coincide testant la concidence du { float x, y ;
point courant avec le point reu en argument :
public :
int point::coincide (point pt) point (float, float) ;
{ if ( (pt.x == x) && (pt.y == y) ) return 1 ; .....
else return 0 ; };
}
nous pouvons dfinir une classe pointcol reprsentant un point dot
Elle sutiliserait ainsi : dune couleur, en lui prvoyant un membre de type point :
point a, b ; class pointcol
boolean ident ; { point p ;
..... int couleur ;
// ident vaudra true si a et b ont memes coordonnees public :
ident = a.coincide (b) ; // ou b.coincide (a) ; pointcol (float, float, int) ;
Bien que ce soit d'un usage plus limit, une fonction ordinaire .....
peut galement recevoir un argument de type classe. Bien entendu, };
elle n'aura alors accs qu'aux membres publics de cet argument.
Dans ce cas, lors de la cration d'un objet de type pointcol, il y
aura tout d'abord appel d'un constructeur de pointcol, puis appel
3.10 Autorfrence : mot cl this d'un constructeur de point ; ce dernier recevra les arguments qu'on
aura mentionn dans len-tte de la dfinition du constructeur de
Au sein dune fonction membre, this reprsente un pointeur sur pointcol. Par exemple, avec :
lobjet layant appel. En voici un exemple (artificiel) dans lequel pointcol::pointcol (float abs, float ord, int coul) : p (abs, ord)
nous exploitons cette possibilit pour crire plus symtriquement la { ...
dfinition de la fonction coincide prcdente.
}
int point::coincide (point pt)
{ if ((this -> x == pt.x)) && (this -> y == pt.y)) return 1 ; on prcise que le constructeur du membre p recevra en argument
else return 0 ; les valeurs abs et ord.
} Si len-tte de pointcol ne mentionnait rien concernant p, il fau-
drait alors que le type point possde un constructeur sans argument
pour que cela soit correct.
3.11 Fonctions membres statiques
Lorsqu'une fonction membre a une action indpendante d'un quel- 3.14 Constructeur par recopie
conque objet de sa classe, on peut la dclarer avec l'attribut static.
Dans ce cas, une telle fonction peut tre appele, sans mentionner
d'objet particulier, en prfixant simplement son nom du nom de la En C++, on parle d'initialisation d'un objet dans des situations tel-
classe concerne, suivi de l'oprateur de rsolution de porte (::). les que :
point a = 5 ; // il doit exister un constructeur un argument
// de type entier
3.12 Cas des objets dynamiques point b = a ; // il doit exister un constructeur un argument
// de type point
Ils sont crs par l'oprateur new, auquel on doit fournir, le cas Le deuxime cas correspond l'initialisation d'un objet l'aide
chant, les valeurs des arguments destins un constructeur, d'un autre objet de mme type, que l'on nomme parfois
comme dans cet exemple qui suppose qu'il existe une classe point initialisation par recopie . L'opration est ralise par appel de ce
possdant le constructeur point (int, int) : que l'on nomme un constructeur par recopie .

Toute reproduction sans autorisation du Centre franais dexploitation du droit de copie est strictement interdite.
Techniques de lIngnieur, trait Informatique industrielle S 8 065 7
PROGRAMMATION EN LANGAGE C++ ______________________________________________________________________________________________________

Mais il existe d'autres situations, plus courantes, qui mettent en Gnralement, la fonction membre fct possdera un argument ou
uvre un tel mcanisme, savoir : une valeur de retour de type A (ce qui justifiera sa dclaration d'ami-
la transmission d'un objet par valeur en argument d'appel ti). Pour compiler sa dclaration (au sein de la dclaration de A), il
d'une fonction ; suffira au compilateur de savoir que A est une classe ; si sa dclara-
la transmission d'un objet par valeur en valeur de retour d'une tion n'est pas connue ce niveau, on pourra se contenter de :
fonction. class A ;
Dans toutes ces situations d'initialisation par recopie, le construc-
teur par recopie employ est : En revanche, pour compiler la dfinition de fct, le compilateur
devra possder les caractristiques de A, donc disposer de sa dcla-
soit un constructeur de la forme type (type &) ou type (const type ration.
&) s'il en existe un ; ce dernier doit alors prendre en charge la recopie
de tous les membres de lobjet, y compris ceux qui sont des objets ; il
peut cependant s'appuyer sur les possibilits de transmission d'infor-
mation entre constructeurs, prsente au paragraphe 3.13 ; 4.3 Toutes les fonctions d'une classe B
soit, dans le cas contraire, ce que l'on nomme un sont amies d'une autre classe A
constructeur de recopie par dfaut , qui recopie les diffrents
membres de l'objet. Si certains de ces membres sont eux-mmes
des objets, la recopie sera ralise par appel de son propre cons- Dans ce cas, plutt que d'utiliser autant de dclarations d'amiti
tructeur par recopie (qui pourra tre soit un constructeur par dfaut, que de fonctions membre, on utilise (dans la dclaration de la classe
soit un constructeur dfini dans la classe correspondante). A) la dclaration (globale) suivante :
friend class B ;

4. Fonctions amies Pour compiler la dclaration de A, on prcisera simplement que B


est une classe par :
class B ;
En C++, l'unit de protection est la classe, et non pas l'objet. Cela
signifie qu'une fonction membre d'une classe peut accder tous Quant la dclaration de la classe B, elle ncessitera gnrale-
les membres privs de n'importe quel objet de sa classe. En revan- ment (ds qu'une de ses fonctions membre possdera un argument
che, ces membres privs restent inaccessibles n'importe quelle ou une valeur de retour de type A) la dclaration de la classe A.
fonction membre d'une autre classe ou n'importe quelle fonction
indpendante.
La notion de fonction amie, ou plus exactement de dclaration
d'amiti , permet de dclarer dans une classe les fonctions que l'on
autorise accder ses membres privs (donnes ou fonctions). Il
5. Surdfinition doprateurs
existe plusieurs situations d'amiti.
C++ vous permet de surdfinir les oprateurs existants, c'est--
dire de leur donner une nouvelle signification lorsqu'ils portent (en
4.1 Fonction indpendante, amie d'une partie ou en totalit) sur des objets de type classe.
classe A
class A 5.1 Mcanisme
{
......
friend --- fct (-----) ; Pour surdfinir un oprateur existant op, on dfinit une fonction
..... nomme operator op (on peut placer un ou plusieurs espaces entre
} le mot operator et l'oprateur, mais ce n'est pas une obligation) :
soit sous forme d'une fonction indpendante (gnralement
La fonction fct ayant le prototype spcifi est autorise accder amie d'une ou de plusieurs classes) ;
aux membres privs de la classe A. soit sous forme d'une fonction membre d'une classe.
Dans le premier cas, si op est un oprateur binaire, la notation
a op b est quivalente :
4.2 Fonction membre d'une classe B,
amie d'une autre classe A operator op (a, b)
Dans le second cas, la mme notation est quivalente :
class A
a.operator op (b)
{
.....
friend --- B:fct (-----) ;
..... 5.2 Possibilits et limites
};

La fonction fct, membre de la classe B, ayant le prototype spcifi, On doit se limiter aux oprateurs existants, en conservant leur
est autorise accder aux membres privs de la classe A. pluralit (unaire, binaire). Les oprateurs ainsi surdfinis gar-
Pour qu'il puisse compiler convenablement la dclaration de A, dent leur priorit et leur associativit habituelle.
donc en particulier la dclaration d'amiti relative fct, le compila- Un oprateur surdfini doit toujours possder un oprande de
teur devra connatre la dclaration de B (mais pas ncessairement type classe (on ne peut donc pas modifier les significations des op-
sa dfinition). rateurs usuels). Il doit donc s'agir :

Toute reproduction sans autorisation du Centre franais dexploitation du droit de copie est strictement interdite.
S 8 065 8 Techniques de lIngnieur, trait Informatique industrielle
______________________________________________________________________________________________________ PROGRAMMATION EN LANGAGE C++

soit d'une fonction membre, auquel cas elle dispose obligatoi- Le processus peut tre rpt loisir : de B, on peut trs bien dri-
rement d'un argument implicite du type de sa classe (this) ; ver une nouvelle classe C, de C driver une nouvelle classe D, et
soit d'une fonction indpendante (ou plutt amie) possdant ainsi de suite.
au moins un argument de type classe.
Il ne faut pas faire d'hypothse sur la signification a priori d'un
oprateur ; par exemple, la signification de += pour une classe ne 6.1 Redfinition dune fonction membre
peut en aucun cas tre dduite de la signification de + et de = pour
cette mme classe.
La classe drive peut redfinir une fonction membre de la classe
de base en fournissant une fonction membre de mme nom (ses
arguments peuvent tre diffrents en nombre et en type ; sa valeur
5.3 Tableau rcapitulatif de retour peut tre de type diffrent). Cest alors cette dernire qui
sera utilise pour tout objet de la classe drive.
(0) class A
Oprateurs surdfinissables en C++ { void f (int) ;
(classs par priorit dcroissante) .....
}
Pluralit Oprateurs Associativit class B extends A
{ int f (int, float) ;
Binaire () (3) [] (3) -> (2)(3) > .....
}
Unaire + - ++ (5) -- (5) ! ~ * & (1) <
new (4) delete (4) (cast) int n, p ; float x ;
Binaire */% > Aa;Bb;
a.f(n) ; // appelle f de A
Binaire +- > p = b.f(n, x) ; // appelle f de B
Binaire << >> >
Binaire < <= > >= >
Binaire == != >
6.2 Modalits d'accs la classe de base
Binaire & >
Les membres privs d'une classe de base ne sont jamais accessi-
Binaire ^ >
bles aux fonctions membre de sa classe drive.
Binaire || > Outre les statuts public ou priv, il existe un statut protg . Un
Binaire && > membre protg se comporte comme un membre priv pour un uti-
lisateur quelconque de la classe ou de la classe drive, mais
Binaire | > comme un membre public pour la classe drive. Voici un tableau
Binaire = (1)(3) += -= *= /= %= < rcapitulant ces diffrents possibilits :
&= ^ = |= <<= >>= (0)
Binaire , (2) >
(1) S'il n'est pas surdfini, il possde une signification par dfaut.
(2) Depuis la version 2.0 seulement. Drivation publique
(3) Doit tre dfini comme fonction membre.
(4) un niveau global (fonction indpendante) avant la version 2.0.
Depuis la version 2.0, il peut en outre tre surdfini pour une classe ; Accs aux Nouveau
dans ce cas, il doit l'tre comme fonction membre. fonctions Accs statut
Statut
(5) Jusqu' la version 3, on ne peut pas distinguer entre les notations membres un utilisateur dans la classe
dans la classe
pr et post . Depuis la version 3, ces oprateurs (lorsqu'ils sont et amies de la classe drive, en cas
dfinis de faon unaire) correspondent la notation pr ; mais il en de base
de la classe drive de nouvelle
existe une dfinition binaire (avec deuxime oprande fictif de type int) drive drivation
qui correspond la notation post .

public oui oui public

protg oui non protg


6. Hritage
priv non non priv

Le concept permet de dfinir une nouvelle classe B dite


drive , partir d'une classe existante A, dite de base ; pour
ce faire, on procde ainsi : Par ailleurs, il existe trois sortes de drivation :
publique : les membres de la classe de base conservent leur
class B : public A // ou private A ou protected A statut dans la classe drive ; c'est la situation la plus usuelle ;
{ // dfinition des membres supplmentaires prive : tous les membres de la classe de base deviennent pri-
// (donnes ou fonctions) vs dans la classe drive ;
// ou redfinition de membres existants dans A protge : les membres publics de la classe de base devien-
// (donnes ou fonctions) nent membres protgs de la classe drive ; les autres membres
}; conservent leur statut.

Toute reproduction sans autorisation du Centre franais dexploitation du droit de copie est strictement interdite.
Techniques de lIngnieur, trait Informatique industrielle S 8 065 9
PROGRAMMATION EN LANGAGE C++ ______________________________________________________________________________________________________

Voici un tableau rcapitulatif : (0)

Diffrentes sortes de drivation


Classe de base Drive publique Drive protge Drive prive

Statut initial Accs FMA Accs Nouveau Accs Nouveau Accs Nouveau Accs
utilisateur statut utilisateur statut utilisateur statut utilisateur
public oui oui public oui protg non priv non
protg oui non protg non protg non priv non
priv oui non priv non priv non priv non

Lorsqu'un membre (donne ou fonction) est redfini dans une B (B & b) : A(b) ; // appel du constructeur par recopie de A
classe drive, il reste toujours possible (soit dans les fonctions // auquel sera transmise la partie de B hrite de A
membre de cette classe, soit pour un client de cette classe) d'acc- // (grce aux rgles de compatibilit entre
der aux membres de mme nom de la classe de base ; il suffit pour // classe drive et classe de base)
cela d'utiliser l'oprateur de rsolution de porte (::), sous rserve,
bien sr, qu'un tel accs soit autoris. d'un constructeur sans argument, si aucun constructeur de la
classe de base n'est mentionn dans l'en-tte ; dans ce cas, il est
ncessaire que la classe de base dispose d'un tel constructeur sans
argument, faute de quoi, on obtiendrait une erreur de compilation.
6.3 Redfinition et surdfinition
Il faut noter quen C++ (contrairement Java), lorsquune fonction 6.6 Consquences de l'hritage
membre est redfinie dans une classe drive, elle masque toutes
les fonctions membres de mme nom de la classe de base (mme Considrons la situation suivante, dans laquelle la classe A pos-
sil y a surdfinition). Autrement dit, la recherche par le compilateur sde une fonction membre f (dont nous ne prcisons pas les argu-
dune fonction de nom donn ne se fait que dans une seule ments) fournissant un rsultat de type t (quelconque : type de base
porte : soit celle de la classe concerne, soit celle dune classe ou type dfini par l'utilisateur, ventuellement type classe) :
de base. On peut dire, en quelque sorte, que la surdfinition ne fran-
chit pas la barrire de lhritage. class A class B : public A
{ ..... { .....
public : };
6.4 Appel des constructeurs t f (...) ;
.....
et des destructeurs };
Aa; // a est du type A
Soit B une classe drive d'une classe de base A. Naturellement,
Bb; // b est du type B, driv de A
ds lors que B possde au moins un constructeur, la cration d'un
objet de type B implique obligatoirement l'appel d'un constructeur Naturellement, un appel tel que a.f(...) a un sens et il fournit un
de B. Mais, de plus, ce constructeur de B doit prvoir des arguments rsultat de type t. Le fait que B hrite publiquement de A permet
destination d'un constructeur de A (une exception a lieu soit si A alors de donner un sens un appel tel que :
n'a pas de constructeur, soit si A possde un constructeur sans
argument). Ces arguments sont prciss dans la dfinition du cons- b.f (...)
tructeur de B, comme dans cet exemple. La fonction f agira sur b, comme s'il tait de type A. Le rsultat
B (int x, int y, char coul) : A (x, y) ; fourni par f sera cependant toujours de type t, mme, notamment,
lorsque le type t est prcisment le type A (le rsultat de f pourra
toutefois tre soumis d'ventuelles conversions s'il est affect
une variable dun type diffrent de t et compatible par affectation).
6.5 Cas particulier du constructeur
par recopie
6.7 Cas particulier de l'oprateur
En plus des rgles dj mentionnes au paragraphe 6.4, il faut d'affectation
ajouter que si la classe drive B ne possde pas de constructeur
par recopie, il y aura appel du constructeur par recopie par dfaut de
Considrons une classe B drivant d'une classe A.
B, lequel procdera ainsi :
Si la classe drive B n'a pas surdfini l'oprateur d'affectation,
appel du constructeur par recopie de A (soit celui qui y a t
l'affectation de deux objets de type B se droule membre membre,
dfini, soit le constructeur par recopie par dfaut) ;
en considrant que la partie hrite de A constitue un membre.
initialisation des membres donnes de B qui ne sont pas hri- Ainsi, les membres propres B sont traits par l'affectation prvue
ts de A. pour leur type (par dfaut ou surdfinie, suivant le cas). La partie
En revanche, un problme se pose lorsque la classe drive dfi- hrite de A est traite par l'affectation prvue dans la classe A.
nit explicitement un constructeur par recopie. En effet, dans ce cas, Si la classe drive B a surdfini l'oprateur =, l'affectation de
il faut tenir compte de ce que l'appel de ce constructeur par recopie deux objets de type B fera ncessairement appel l'oprateur =
entranera l'appel : dfini dans B. Celui de A ne sera pas appel, mme s'il a t surd-
du constructeur de la classe de base mentionn dans son en- fini. Il faudra donc que l'oprateur = de B prenne en charge tout ce
tte, comme dans cet exemple (il s'agit ici d'un constructeur par qui concerne l'affectation d'objets de type B, y compris pour ce qui
recopie de la classe de base, mais il pourrait s'agir de n'importe quel est des membres hrits de A (quitte faire appel l'oprateur
autre constructeur). d'affectation de A).

Toute reproduction sans autorisation du Centre franais dexploitation du droit de copie est strictement interdite.
S 8 065 10 Techniques de lIngnieur, trait Informatique industrielle
______________________________________________________________________________________________________ PROGRAMMATION EN LANGAGE C++

6.8 Compatibilit entre objets pointcoul (.....) : point (.....), coul (.....)
d'une classe de base et objets | | |
| | |
d'une classe drive
arguments arguments arguments
pointcoul point coul
Considrons :
class A class B : public A
{ ..... { ..... 6.9.3 Classes virtuelles
}; };
Aa; // a est du type A Par le biais de drivations successives, il est tout fait possible
Bb; // b est du type B, driv de A qu'une classe hrite deux fois d'une mme classe.
A * ada ; // ada est un pointeur sur des objets de type A
B * adb ; // adb est un pointeur sur des objets de type B Exemple : dans lequel D hrite deux fois de A.

Il existe deux conversions implicites : class B : public A


d'un objet d'un type driv dans un objet d'un type de base. { ..... } ;
Ainsi l'affectation a = b est lgale : elle revient convertir b dans le class C : public A
type A (c'est--dire, en fait, ne considrer de b que ce qui est du { ..... } ;
type A) et affecter ce rsultat a (avec appel, soit de l'oprateur class D : public B, public C
d'affectation de A si celui-ci a t surdfini, soit de l'oprateur
d'affectation par dfaut de A). L'affectation inverse b = a est, quant { ..... } ;
elle, illgale ;
d'un pointeur sur une classe drive en un pointeur sur une Dans ce cas, les membres donnes de la classe en question
classe de base. Ainsi l'affectation ada = adb est lgale, tandis que (A dans notre exemple) apparaissent deux fois dans la classe dri-
adb = ada est illgale (elle peut cependant tre force par emploi de ve de deuxime niveau (ici D). Naturellement, il est ncessaire de
l'oprateur de cast : adb = (B*) ada). faire appel l'oprateur de rsolution de porte (::) pour lever
l'ambigut. Si l'on souhaite que de tels membres n'apparaissent
qu'une seule fois dans la classe drive de deuxime niveau, il faut,
dans les dclarations des drives de premier niveau (ici B et C),
6.9 Hritage multiple dclarer avec l'attribut virtual la classe dont on veut viter la dupli-
cation (ici A).
Voici comment on procderait dans l'exemple prcdent (le mot
6.9.1 Mcanisme virtual peut tre indiffremment plac avant ou aprs le mot public
ou le mot private).
C++ autorise l'hritage multiple : une classe peut hriter de
plusieurs autres classes, comme dans cet exemple o la classe class B : public virtual A
pointcol hrite simultanment des classes point et coul : { ..... } ;
class pointcol : public point, public coul class C : public virtual A
// chaque drivation, ici publique { ..... } ;
// pourrait tre prive ou protge class D : public B, public C
{ // dfinition des membres supplmentaires { ..... } ;
// ou redfinition de membres existants dj
// dans les classes point ou coul
}; Lorsque l'on a ainsi dclar une classe virtuelle, il est ncessaire
que les constructeurs d'ventuelles classes drives puissent prci-
Chacune des drivations peut tre publique, prive ou protge. ser les informations transmettre au constructeur de cette classe
Les modalits d'accs aux membres de chacune des classes de base virtuelle (dans le cas usuel o l'on autorise la duplication, ce pro-
restent les mmes que dans le cas d'une drivation simple . blme ne se pose plus ; en effet, chaque constructeur transmet les
L'oprateur de rsolution de porte (::) peut tre utilis : informations aux classes ascendantes dont les constructeurs trans-
soit lorsque l'on veut accder un membre d'une des classes mettent, leur tour, les informations aux constructeurs de chacune
de base, alors qu'il est redfini dans la classe drive ; des occurrences de la classe en question ces informations pou-
vant ventuellement tre diffrentes). Dans ce cas, on le prcise
soit lorsque deux classes de base possdent un membre de
dans l'en-tte du constructeur de la classe drive, en plus des argu-
mme nom et qu'il faut alors prciser celui qui nous intresse.
ments destins aux constructeurs des classes du niveau immdiate-
ment suprieur, comme dans cet exemple.
6.9.2 Appel des constructeurs et des destructeurs D ( .....) : B (.....), C ( ..... ), A ( ..... )
| | | |
La cration d'un objet entrane l'appel du constructeur de chacune
des classes de base, dans l'ordre o ces constructeurs sont men- | | | |
tionns dans la dclaration de la classe drive (ici, point puis coul arguments arguments arguments arguments
puisque nous avons crit class pointcol : public point, public coul). de D pour B pour C pour A
Les destructeurs sont appels dans l'ordre inverse.
Le constructeur de la classe drive peut mentionner, dans son De plus, dans ce cas, les constructeurs des classes B et C (qui ont
en-tte, des informations retransmettre chacun des construc- dclar que A tait virtuelle ) n'auront plus spcifier d'informa-
teurs des classes de base (ce sera gnralement indispensable, sauf tions pour un constructeur de A.
si une classe de base possde un constructeur sans argument ou si Enfin, le constructeur d'une classe virtuelle est toujours appel
elle ne dispose pas du tout de constructeur). avant les autres.

Toute reproduction sans autorisation du Centre franais dexploitation du droit de copie est strictement interdite.
Techniques de lIngnieur, trait Informatique industrielle S 8 065 11
PROGRAMMATION EN LANGAGE C++ ______________________________________________________________________________________________________

7. Fonctions virtuelles 7.3 Fonctions virtuelles pures


et polymorphisme Une fonction virtuelle pure se dclare avec une initialisation
zro, comme dans :
virtual void affiche () = 0 ;
Par le biais du mcanisme des fonctions virtuelles, C++ permet de
raliser la ligature dynamique des fonctions membres et, partant, de Lorsqu'une classe comporte au moins une fonction virtuelle pure,
mettre en oeuvre le polymorphisme. Il sagit l dun concept extr- elle est considre comme abstraite , c'est--dire qu'il n'est plus
mement puissant qui permet dappliquer une mme opration des possible de crer des objets de son type.
objets de types diffrents, sans quil ne soit ncessaire den conna-
tre le type exact. Avant de prsenter les fonctions virtuelles, nous Une fonction dclare virtuelle pure dans une classe de base peut
commencerons par montrer les contraintes qui psent sur le choix ne pas tre dclare dans une classe drive et, dans ce cas, elle est
dune mthode dans un contexte dhritage. nouveau implicitement fonction virtuelle pure de cette classe dri-
ve.

7.1 Typage statique des objets


8. Flots dentre et de sortie
Les rgles de compatibilit entre une classe de base et une classe
drive permettent d'affecter un pointeur sur une classe de base la Un flot est un canal recevant (flot d' entre ) ou fournissant (flot
valeur d'un pointeur sur une classe drive. Toutefois, par dfaut, le de sortie ) de l'information. Ce canal est associ un priphri-
type des objets points est dfini lors de la compilation. que ou un fichier. Un flot d'entre est un objet de type istream tan-
dis qu'un flot de sortie est un objet de type ostream. Le flot cout est
class A class B : public A un flot de sortie prdfini, connect la sortie standard stdout ; de
{ ..... { ..... mme, le flot cin est un flot d'entre prdfini, connect l'entre
public : public : standard stdin.
void fct (...) ; void fct (...) ;
..... .....
}; };
8.1 Classe ostream
A * pta ;
B * ptb ;
8.1.1 Prsentation
Dans cet exemple, une affectation telle que pta = ptb est autori-
se. Nanmoins, quel que soit le contenu de pta (autrement dit, quel Elle surdfinit l'oprateur << sous la forme d'une fonction mem-
que soit l'objet point par pta), pta->fct(...) appelle toujours la fonc- bre :
tion fct de la classe A.
ostream & operator << (expression)
L'expression correspondant son deuxime oprande peut tre
d'un type de base quelconque, y compris char, char * (on obtient la
7.2 Fonctions virtuelles chane pointe) ou un pointeur sur un type quelconque autre que
char (on obtient la valeur du pointeur) ; pour obtenir la valeur de
l'adresse d'une chane, on la convertit artificiellement en un poin-
L'emploi des fonctions virtuelles permet d'viter les problmes teur de type void *.
inhrents au typage statique. Lorsqu'une fonction est dclare vir-
Nous en avons un exemple avec le flot prdfini cout au paragra-
tuelle (mot cl virtual) dans une classe, les appels une telle fonc-
phe 2.3.
tion ou n'importe laquelle de ses redfinitions dans des classes
drives sont "rsolus" au moment de l'excution, selon le type de
l'objet concern. On parle de typage dynamique des objets (ou de
ligature dynamique des fonctions).
8.1.2 Principales fonctions membre

ostream & put (char c)


class A class B : public A
{ ..... { .....
public : public : transmet au flot correspondant le caractre c.
virtual void fct (...) ; void fct (...) ; ostream & write (void * adr, int long)
..... .....
}; }; envoie long caractres, prlevs partir de l'adresse adr.
A * pta ;

Dans cet exemple, l'instruction pta->fct (...) appellera la fonction


8.2 Classe istream
fct de la classe correspondant rellement au type de l'objet point
par pta.
8.2.1 Prsentation
On notera que, par nature, le mcanisme de ligature dynamique
est limit une hirarchie de classes ; souvent, pour qu'il puisse
Elle surdfinit l'oprateur >> sous la forme d'une fonction mem-
s'appliquer toute une bibliothque de classes, on sera amen
bre :
faire hriter toutes les classes de la bibliothque d'une mme classe
de base. istream & operator >> (type_de_base &)

Toute reproduction sans autorisation du Centre franais dexploitation du droit de copie est strictement interdite.
S 8 065 12 Techniques de lIngnieur, trait Informatique industrielle
______________________________________________________________________________________________________ PROGRAMMATION EN LANGAGE C++

Le type_de_base peut tre quelconque, pour peu qu'il ne s'agisse 8.4 Association d'un flot un fichier
pas d'un pointeur (char * est cependant accept ; il correspond
l'entre d'une chane de caractres, et non d'une adresse).
Les espaces_blancs (espace, tabulation horizontale \t ou verti- La classe ofstream, drivant de ostream, permet de crer un flot
cale \v, fin de ligne \n et changement de page \f ) servent de de sortie associ un fichier :
dlimiteurs (comme dans scanf ), y compris pour les chanes de ofstream flot (char * nomfich, mode_d_ouverture)
caractres.
Nous en avons un exemple avec le flot prdfini cin, au paragra- Le mode douverture est dfini par un entier dont on positionne
phe 2.3. certains bits en utilisant des constantes prdfinies (que lon peut
combiner par loprateur ||) choisies parmi les suivantes :
(0)
8.2.2 Principales fonctions membres

istream & get (char & c) Diffrents modes d'ouverture d'un fichier

extrait un caractre du flot d'entre et le range dans c. Mode Action

int get () ios::in Ouverture en lecture (obligatoire pour la classe


ifstream)
extrait un caractre du flot d'entre et en renvoie la valeur (sous
forme d'un entier) ; fournit EOF en cas de fin de fichier. ios::out Ouverture en criture (obligatoire pour la classe
ofstream)
istream & getline (char * ch, int taille, char delim = '\n')
ios::app Ouverture en ajout de donnes (criture en fin de
lit des caractres sur le flot et les place l'adresse ch (en compl- fichier)
tant par un caractre nul de fin de chane). Elle s'interrompt
ios::trunc Si le fichier existe, son contenu est perdu
lorsqu'une des deux conditions suivantes est satisfaite : (obligatoire si ios::out est activ sans ios::ate ni
le caractre delim a t trouv : (il n'est pas recopi en ios::app)
mmoire) ;
ios::binary Utilis seulement dans les implmentations qui
taille 1 caractres ont t lus. distinguent les fichiers texte des autres
istream & read (void * adr, int taille) Le fichier est ouvert en mode "binaire" ou encore
"non translat"
lit taille caractres sur le flot et les range partir de l'adresse adr.

La fonction membre seekp (dplacement, origine) permet d'agir


8.3 Surdfinition de << et >> pour sur le pointeur de fichier.
des types classe De mme, la classe ifstream, drivant de istream, permet de crer
un flot d'entre associ un fichier :
On surdfinira << pour une classe quelconque T, sous forme de
ifstream flot (char * nomfich, mode_d_ouverture)
fonctions amies, en utilisant ces canevas :
ostream & operator << (ostream sortie, T objet) La fonction membre seekg (dplacement, origine) permet d'agir
{ sur le pointeur de fichier.
// Envoi sur le flot sortie des membres de objet Dans tous les cas, la fonction close permet de fermer le fichier.
// en utilisant les possibilits classiques de <<
// pour les types de base c'est--dire
// des instructions de la forme :
// sortie << ..... ;
return sortie ;
9. Patrons de fonctions
}

On peut alors envoyer un objet de type T sur un flot quelconque ; Introduite par la version 3, la notion de patron de fonctions per-
par exemple : met de dfinir ce que l'on nomme souvent des fonctions gn-
riques . Plus prcisment, l'aide d'une unique dfinition compor-
T a, b ; // objets de type T
tant des paramtres de type , on dcrit toute une famille de fonc-
.....
tions ; le compilateur fabrique (on dit aussi instancie ) la ou
cout << a << b ;
les fonctions ncessaires la demande (on nomme souvent ces ins-
De mme, on surdfinira >> pour une classe donne T, en utilisant tances fonctions patrons ).
ce canevas :
istream & operator >> (istream & entree, T & objet)
{ 9.1 Dfinition
// Lecture des informations correspondant aux
// diffrents membres de objet en utilisant les
// possibilits classiques de >> pour les types de base On prcise les paramtres (muets) de type, en faisant prcder
// c'est--dire des instructions de la forme : chacun du mot (relativement arbitraire) class sous la forme template
// entree >> ..... ; <class ..., class ..., ...>. La dfinition de la fonction est classique, hor-
return entree ; mis le fait que les paramtres muets de type peuvent tre employs
} n'importe o un type effectif est permis.

Toute reproduction sans autorisation du Centre franais dexploitation du droit de copie est strictement interdite.
Techniques de lIngnieur, trait Informatique industrielle S 8 065 13
PROGRAMMATION EN LANGAGE C++ ______________________________________________________________________________________________________

template <class T, class U> void fct (T a, T * b, U c) template <class T> int compte (T * tab, int n)
{ { // ici, on peut se servir de la valeur de l'entier n
Tx; // variable locale x de type T // comme on le ferait dans n'importe quelle fonction ordinaire
U * adr ; // variable locale adr de type U * }
... Un patron de fonctions peut disposer d'un ou de plusieurs paramtres
adr = new T [10] ; // allocation tableau de 10 lments de type T expression. Lors de l'appel, leur type n'a plus besoin de correspondre
... exactement celui attendu : il suffit qu'il soit acceptable par affectation,
n = sizeof (T) ; // une instruction utilisant le type T comme dans n'importe quel appel d'une fonction ordinaire.
...
}
9.4 Surdfinition de patrons de fonctions
Remarque et spcialisation de fonctions
Une instruction telle que (T dsignant un type quelconque) : de patrons
T x (3) ;
On peut dfinir plusieurs patrons de mme nom, possdant des
est lgale mme si T n'est pas un type classe ; dans ce dernier paramtres (de type ou expression) diffrents. La seule rgle res-
cas, elle est simplement quivalente : pecter dans ce cas est que l'appel d'une fonction de ce nom ne doit
pas conduire une ambigut : un seul patron de fonctions doit pou-
Tx=3; voir tre utilis chaque fois.
Par ailleurs, il est possible de fournir la dfinition d'une ou plu-
sieurs fonctions particulires qui seront utilises en lieu et place de
9.2 Instanciation d'une fonction patron celle instancie par un patron.
template <class T> T min (T a, T b) // patron de fonctions
Chaque fois que l'on utilise une fonction ayant un nom de patron, { ... }
le compilateur cherche utiliser ce patron pour crer (instancier) char * min (char * cha, char * chb) // version spcialise
une fonction adquate. Pour ce faire, il cherche raliser une corres- { ... } // pour le type char *
pondance absolue des types : aucune conversion, qu'il s'agisse de int n, p;
promotion numrique ou de conversion standard n'est permise. char * adr1, * adr2 ;
min (n, p) // appelle la fonction
Voici des exemples utilisant notre patron prcdent. // instancie par
int n, p ; float x ; char c ; // le patron gnral, soit ici :
int * adi ; float * adf ; // int min (int, int)
class point ; point p ; point * adp ; min (adr1, adr2) // appelle la fonction
// spcialise :
fct (n, adi, x) ; // instancie la fonction : // char * min (char *, char *)
// void fct (int, int *, float)
fct (n, adi, p) // instancie la fonction :
// void fct (int, int *, int) 9.5 Algorithme d'instanciation
fct (x, adf, p) ; // instancie la fonction : ou d'appel d'une fonction
// void fct (float, float *, int)
fct (c, adi, x) ; // erreur char et int * ne correspondent
Prcisons comment doivent tre amnages les rgles de recher-
// pas T et T* ( pas de conversion)
che d'une fonction surdfinie, dans le cas o il existe un ou plu-
fct (&n, &adi, x) ; // instancie la fonction :
sieurs patrons de fonctions.
// void fct (int *, int * *, float)
fct (p, adp, n) ; // instancie la fonction : Lors d'un appel de fonction, le compilateur recherche tout
// void fct (point, point *, int) d'abord une correspondance exacte (mme nombre et mmes
types dargument) avec les fonctions ordinaires . S'il y a ambi-
D'une manire gnrale, il est ncessaire que chaque paramtre gut, la recherche choue (comme l'accoutume). Si aucune fonc-
de type apparaisse au moins une fois dans l'en-tte du patron. tion ordinaire ne convient, on examine alors tous les patrons
ayant le nom voulu (en ne considrant que les paramtres de type).
Si une seule correspondance exacte est trouve, la fonction corres-
Remarque pondante est instancie et le problme est rsolu. S'il y en a plu-
La dfinition d'un patron de fonctions ne peut pas tre compi- sieurs, la recherche choue.
le seule ; de toute faon, elle doit tre connue du compilateur
pour qu'il puisse instancier la bonne fonction patron. En gn- Enfin, si aucun patron de fonction ne convient, on examine nou-
ral, les dfinitions de patrons de fonctions figureront dans des veau toutes les fonctions ordinaires en les traitant cette fois
fichiers d'extension h, de faon viter d'avoir en fournir sys- comme de simples fonctions surdfinies (promotions numriques,
tmatiquement la liste. conversions standard...).

9.3 Paramtres expression d'un patron 10. Patrons de classes


de fonctions
La notion de patron de classes permet de dfinir ce que l'on
nomme aussi des classes gnriques . Plus prcisment, l'aide
Un paramtre expression d'un patron de fonctions se prsente d'une seule dfinition comportant des paramtres de type et des
comme un argument usuel de fonction ; il n'apparat pas dans la paramtres expression, on dcrit toute une famille de classes ; le
liste de paramtres de type (template) et il doit apparatre dans l'en- compilateur fabrique (instancie) la ou les classes ncessaires la
tte du patron. demande (on nomme souvent ces instances des classes patrons ).

Toute reproduction sans autorisation du Centre franais dexploitation du droit de copie est strictement interdite.
S 8 065 14 Techniques de lIngnieur, trait Informatique industrielle
______________________________________________________________________________________________________ PROGRAMMATION EN LANGAGE C++

10.1 Dfinition 10.3.1 En spcialisant une fonction membre

Par exemple, avec ce patron :


On prcise les paramtres de type en les faisant prcder du mot
cl class et les paramtres expression en mentionnant leur type template <class T, int n> class tableau { ..... } ;
dans une liste de paramtres introduite par le mot template (comme
on pourra crire une version spcialise de constructeur pour le cas
pour les patrons de fonctions, avec cette diffrence qu'ici, tous les
o T est le type point et o n vaut 10 en procdant ainsi :
paramtres type ou expression apparaissent).
tableau <point, 10>:: tableau (...) { ..... }
template <class T, class U, int n> class gene
{ // ici, T dsigne un type quelconque,
// n une valeur entire quelconque 10.3.2 En spcialisant une classe
};
Dans ce cas, on peut ventuellement spcialiser tout ou une partie
Si une fonction membre est dfinie (ce qui est le cas usuel) l'ext- des fonctions membres, mais ce n'est pas ncessaire.
rieur de la dfinition du patron, il faut rappeler au compilateur la liste
de paramtres (template) et prfixer l'en-tte de la fonction membre Par exemple, avec ce patron :
du nom du patron accompagn de ses paramtres. Par exemple, template <class T> class point { ..... } ;
pour un constructeur de notre patron de classes prcdent :
on peut fournir une version spcialise pour le cas o T est le type
template <class T, class U, int n> gene <T, U, n>::gene (...)
char en procdant ainsi :
{ ..... }
class point <char>
{ // nouvelle dfinition de la classe point pour les caractres
};
10.2 Instanciation d'une classe patron

On dclare une classe patron en fournissant la suite du nom de 10.4 Identit de classes patron
patron un nombre de paramtres effectifs (noms de types ou
expressions) correspondant aux paramtres figurant dans la liste
(template). Les paramtres expression doivent obligatoirement tre On ne peut affecter entre eux que deux objets de mme type.
des expressions constantes du mme type que celui figurant dans la Dans le cas d'objets d'un type classe patron, on considre qu'il y a
liste. identit de type lorsque leurs paramtres de types sont identiques
et que les paramtres expression ont les mmes valeurs.
Exemple : avec notre prcdent patron (on suppose que pt est une
classe) :
class gene <int, float, 5> c1 ; // T = int, U = float, n=5 10.5 Classes patron et hritage
class gene <int, int, 12> c2 ; // T = int, U = int, n = 12
const int NV=100 ;
class gene <pt, double, NV> c3 ; // T = pt, U = double, n=100 On peut combiner de plusieurs faons l'hritage avec la notion
int n = 5 ; de patron de classes.
class gene <int, double, n> c4 ; // erreur : n n'est pas constant
const char C = 'e' ; Classe ordinaire drive d'une classe patron
class gene <int, double, C> c5 ; // erreur : C de type char et non int Par exemple, si A est une classe patron dfinie par template
<class T> A :
Un paramtre de type effectif peut lui-mme tre une classe
class B : public A <int> // B drive de la classe patron A<int>
patron. Par exemple, si nous avons dfini un patron de classes point
par : on obtient une seule classe nomme B.
template <class T> class point { ..... } ; Patron de classes driv d'une classe ordinaire
Voici des instances possibles de gene : Par exemple, si A est une classe ordinaire :
class gene <point<int>, float, 10> c5 ;
template <class T> class B : public A
// T=point<int>, U=float, n=10
class gene <point<char>, point<float>, 5> c6 ; on obtient une famille de classes (de paramtre de type T).
// T=point<int>, U=point<float>, n=5 Patron de classes driv d'un patron de classes
Un patron de classes peut comporter des membres (donnes ou Par exemple, si A est une classe patron dfinie par template
fonctions) statiques ; dans ce cas, chaque instance de la classe dis- <class T> A, on peut :
pose de son propre jeu de membres statiques. dfinir une nouvelle famille de fonctions drives par :
template <class T> class B : public A <T>

10.3 Spcialisation d'un patron Dans ce cas, il existe autant de classes drives possibles que de
classes de base possibles.
de classes
dfinir une nouvelle famille de fonctions drives par :
template <class T, class U> class B : public A <T>
Un patron de classes ne peut pas tre surdfini (on ne peut pas
dfinir deux patrons de mme nom). En revanche, on peut spciali- Dans ce cas, on peut dire que chaque classe de base possible peut
ser un patron de classes de diffrentes manires. engendrer une famille de classes drives (de paramtre de type U).

Toute reproduction sans autorisation du Centre franais dexploitation du droit de copie est strictement interdite.
Techniques de lIngnieur, trait Informatique industrielle S 8 065 15
PROGRAMMATION EN LANGAGE C++ ______________________________________________________________________________________________________

11. Gestion des exceptions 12.1 Notions de conteneur, ditrateur


et dalgorithme
C++ dispose d'un mcanisme dit de gestion des exceptions. Une
exception est une rupture de squence (pas un appel de fonction !)
12.1.1 Notion de conteneur
dclenche (on dit aussi leve ) par un programme l'aide de
l'instruction throw dans laquelle on mentionne une expression quel- La bibliothque standard fournit un ensemble de classes dites
conque. Il y a alors branchement un ensemble d'instructions, dit conteneurs, permettant de reprsenter les structures de donnes les
gestionnaire d'exceptions , choisi en fonction de la nature de plus rpandues telles que les vecteurs, les listes, les ensembles ou
l'expression indique throw. les tableaux associatifs. Il s'agit de patrons de classes paramtrs
tout naturellement par le type de leurs lments. Par exemple, on
Pour qu'une portion de programme puisse intercepter une excep- pourra construire une liste d'entiers, un vecteur de flottants ou une
tion, il est ncessaire qu'elle figure l'intrieur d'un bloc prcd du liste de points (point tant une classe) par les dclarations suivantes :
mot cl try. Ce dernier doit tre suivi d'une ou plusieurs instructions
catch reprsentant les diffrents gestionnaires correspondants, list <int> li ; /* liste vide dlments de type int */
comme dans ce schma : vector <double> ld ; /* vecteur vide dlments de type double */
try list <point> lp ; /* liste vide dlments de type point */
{ ..... // instructions susceptibles de lever une exception, soit
// directement par throw (exp), soit par le biais Chacune de ces classes conteneur dispose de fonctionnalits
// de fonctions appeles appropries dont on pourrait penser, a priori, qu'elles sont trs dif-
} frentes d'un conteneur l'autre. En ralit, les concepteurs de STL
catch (type_a ...) ont fait un gros effort d'homognisation et beaucoup de fonctions
{ ..... // traitement de l'exception correspondant au type membres sont communes diffrents conteneurs. On peut dire que,
type_a ds qu'une action donne est ralisable avec deux conteneurs diff-
} rents, elle se programme de la mme manire.
catch (type_b ...)
{ ..... // traitement de l'exception correspondant au type
type_b 12.1.2 Notion d'itrateur
}
.....
catch (type_n ...) C'est dans ce souci d'homognisation des actions sur un conte-
{ ..... // traitement de l'exception correspondant au type neur qu'a t introduite la notion d'itrateur. Un itrateur est un
type_n objet dfini gnralement par la classe conteneur concerne qui
} gnralise la notion de pointeur :
un instant donn, un itrateur possde une valeur qui dsi-
Un gestionnaire d'exceptions peut contenir des instructions exit gne un lment donn d'un conteneur ; on dira souvent qu'un itra-
ou abort qui mettent fin l'excution du programme. Une instruc- teur pointe sur un lment d'un conteneur ;
tion return fait sortir de la fonction ayant lev l'exception. Dans les
un itrateur peut tre incrment par l'oprateur ++, de ma-
autres cas (rarement utiliss), on passe aux instructions suivant le
nire pointer sur l'lment suivant du mme conteneur ; cela n'est
bloc try concern.
possible que parce que les conteneurs sont toujours ordonns sui-
D'une manire gnrale, le gestionnaire d'une exception est vant une certaine squence ;
dfini indpendamment des fonctions susceptibles de la dclen- un itrateur peut tre drfrenc, comme un pointeur, en uti-
cher. Ainsi, partir du moment o la dfinition d'une classe est lisant l'oprateur * ; par exemple, si it est un itrateur sur une liste
spare de son utilisation (ce qui est souvent le cas en pratique), il de points, *it dsigne un point de cette liste ;
est tout fait possible de prvoir un gestionnaire d'exception diff- deux itrateurs sur un mme conteneur peuvent tre compa-
rent d'une utilisation une autre d'une mme classe. rs par galit ou ingalit.
En ce qui concerne lalgorithme de choix dun gestionnaire
Tous les conteneurs fournissent un itrateur portant le nom itera-
dexceptions, il faut savoir que lorsqu'une exception est leve par
tor et possdant au minimum les proprits que nous venons d'nu-
throw, avec le type T, on recherche, dans cet ordre : un gestionnaire
mrer qui correspondent ce qu'on nomme un itrateur
correspondant l'un des types suivants : type T, type de base de T,
unidirectionnel. Certains itrateurs pourront possder des propri-
pointeur sur une classe drive (si T est d'un type pointeur sur une
ts supplmentaires, en particulier :
classe), type indtermin (indiqu par catch(...)) dans le gestion-
naire. Il est ainsi possible, suivant les circonstances, daffiner plus dcrmentation par l'oprateur -- ; comme cette possibilit
ou moins lanalyse des exceptions. s'ajoute alors celle qui est offerte par ++, l'itrateur est alors dit
bidirectionnel ;
accs direct ; dans ce cas, si it est un tel itrateur, l'expression
it+i a un sens ; souvent, l'oprateur [] est alors dfini, de manire
12. Bibliothque standard que it[i] soit quivalent *(it+i) ; en outre, un tel itrateur peut tre
compar par ingalit.

Comme celle du C, la norme du C++ comprend la dfinition d'une


bibliothque standard. Bien entendu, on y trouve toutes les fonc- 12.1.3 Exemples dutilisation ditrateurs
tions prvues dans les versions C++ d'avant la norme, qu'il s'agisse
des flots dcrits prcdemment ou des fonctions de la bibliothque
standard du C. Mais, on y dcouvre surtout bon nombre de nou- Tous les conteneurs fournissent des valeurs particulires de type
veauts originales. La plupart d'entre elles sont constitues de iterator, sous forme des fonctions membres begin() et end(), de
patrons de classes et de fonctions provenant en majorit d'une sorte que, quel que soit le conteneur, le canevas suivant, prsent ici
bibliothque du domaine public, nomme Standard Template sur une liste de points, est toujours utilisable pour parcourir squen-
Library (en abrg STL) et dveloppe chez Hewlett Packard. tiellement un conteneur de son dbut jusqu' sa fin :

Toute reproduction sans autorisation du Centre franais dexploitation du droit de copie est strictement interdite.
S 8 065 16 Techniques de lIngnieur, trait Informatique industrielle
______________________________________________________________________________________________________ PROGRAMMATION EN LANGAGE C++

list<point> lp ; on procdera de faon similaire (en se contentant de remplacer v par l) :


..... n = count (l.begin(), l.end(), 1) ;
list<point>::iterator il ; /* itrateur sur une liste de points */
/* compte le nombre d'lments valant 1 */
for (il = lp.begin() ; il != lp.end() ; il++)
{ /* dans la squence [l.begin(), l.end()) */
/* ici *il dsigne l'lment courant de la liste de points lp */ /* autrement dit, dans tout le conteneur l */
}
D'une manire gnrale, comme le laissent entendre ces deux
On notera la particularit des valeurs des itrateurs de fin qui exemples, les algorithmes s'appliquent, non pas un conteneur,
consiste pointer, non pas sur le dernier lment d'un conteneur, mais une squence dfinie par un intervalle d'itrateur ; ici, cette
mais juste aprs. D'ailleurs, lorsqu'un conteneur est vide, begin() squence correspondait l'intgralit du conteneur.
possde la mme valeur que end(), de sorte que le canevas prc-
Certains algorithmes permettront facilement de recopier des
dent fonctionne toujours convenablement.
informations d'un conteneur d'un type donn vers un conteneur
d'un autre type, pour peu que ses lments soient du mme type
Par ailleurs, toutes les classes conteneur pour lesquelles iterator
que ceux du premier conteneur.
est au moins bidirectionnel (on peut donc lui appliquer ++ et --) dis-
posent d'un second itrateur not reverse_iterator. Construit par- Exemple : comment recopier un vecteur d'entiers dans une liste
tir du premier, il permet d'explorer le conteneur suivant l'ordre d'entiers.
inverse. Dans ce cas, la signification de ++ et --, appliqus cet it- vector<int> v ; /* vecteur d'entiers */
rateur, est alors adapte en consquence ; en outre, il existe gale- list<int> l ; /* liste d'entiers */
ment des valeurs particulires de type reverse_iterator fournies par .....
les fonctions membres rbegin() et rend() ; on peut dire que rbegin() copy (v.begin(), v.end(), l.begin() ) ;
pointe sur le dernier lment du conteneur, tandis que rend() pointe /* recopie l'intervalle [v.begin(), v.end()), */
juste avant le premier. Voici comment parcourir une liste de points /* partir de l'emplacement point par l.begin() */
dans l'ordre inverse :

list<point> lp ; 12.2 Diffrents conteneurs et algorithmes


.....
list<point>::reverse_iterator ril ; /* itrateur inverse sur */ Dune manire gnrale, la bibliothque standard fournit des
/* une liste de points */ conteneurs pour les diffrentes structures de donnes suivantes :
for (ril = lp.rbegin() ; ril != lp.rend() ; ril++) vecteurs dynamiques ;
{ listes doublement chanes ;
/* ici *ril dsigne l'lment courant de la liste de points lp */ piles ;
} listes dattente ;
tables associatives ;
ensembles.
12.1.4 Notion d'algorithme Les principaux algorithmes sont les suivants :
initialisation ;
copie ;
La notion d'algorithme est tout aussi originale que les deux prc- recherche de maximum ou de minimum ;
dentes. Elle se fonde sur le fait que, par le biais d'un itrateur, beau- remplacement de valeurs ;
coup d'oprations peuvent tre appliques un conteneur, quels permutations circulaires ;
que soient sa nature et le type de ses lments. Par exemple, on suppression dlments rpondant un certain critre ;
pourra trouver le premier lment ayant une valeur donne aussi tris ;
bien dans une liste, un vecteur ou ensemble ; il faudra cependant recherche binaire ;
que l'galit de deux lments soit convenablement dfinie soit par fusion ;
dfaut, soit par surdfinition de l'oprateur ==. De mme, on pourra oprations ensemblistes.
trier un conteneur d'objets de type T, pour peu que ce conteneur dis-
pose d'un itrateur accs direct et que l'on ait dfini une relation
d'ordre sur le type T, par exemple en surdfinissant l'oprateur <. 12.3 Autres classes
Les diffrents algorithmes sont fournis sous forme de patrons de Outre les classes et algorithmes que nous venons dvoquer, la
fonctions, paramtrs par le type des itrateurs qui leurs sont four- bibliothque standard dispose de quelques classes spcialises
nis en argument. L encore, cela conduit des programmes trs nentrant plus dans le cadre de la STL, savoir :
homognes puisque les mmes fonctions pourront tre appliques
des conteneurs diffrents. Par exemple, pour compter le nombre la classe string qui propose un cadre trs souple de manipula-
d'lments gaux un dans un vecteur dclar par : tion de chanes de caractres en offrant les fonctionnalits tradition-
nelles que l'on peut attendre d'un tel type : gestion dynamique
vector<int> v ; /* vecteur d'entiers */ transparente des emplacements correspondants, affectation, conca-
tnation, recherche de sous-chanes, insertions ou suppression de
on pourra procder ainsi : sous-chanes... ;
quelques patrons de classes destins faciliter les oprations
n = count (v.begin(), v.end(), 1) ; mathmatiques usuelles sur les nombres complexes et sur les vec-
/* compte le nombre d'lments valant 1 */ teurs, de manire doter C++ de possibilits voisines de celles de
/* dans la squence [v.begin(), v.end()) */ Fortran 90 et favoriser son utilisation sur des calculateurs vecto-
/* autrement dit, dans tout le conteneur v */ riels ou parallles. Il s'agit essentiellement des classes complex, des
classes valarray et des classes associes.
Pour compter le nombre d'lments gaux un dans une liste
dclare : Pour approfondir le sujet, le lecteur pourra se reporter en
list<int> l ; /* liste d'entiers */ bibliographie aux rfrences [1][2][3][4][5][6] et [7].

Toute reproduction sans autorisation du Centre franais dexploitation du droit de copie est strictement interdite.
Techniques de lIngnieur, trait Informatique industrielle S 8 065 17
PROGRAMMATION EN LANGAGE C++ ______________________________________________________________________________________________________

Rfrences bibliographiques

[1] MEYER (B.). Object-Oriented Software [4] LIPPMAN (S.B.). C++ Primer, Third Edition. [6] DELANNOY (C.). Exercices en langage C++,
Construction. C.A.R. Hare Series Editor, Reading, MA : Addison-Welsley Publishing nouvelle dition. dition Eyrolles, 61, boule-
Englewood Cliffs, NJ: Prentice Hall, 1988. Company, 1998. vard St Germain 75240 Paris, 2002.
[2] STROUSTRUP (B.). The C++ Programming
Langage, Third Edition. Reading, MA : Addi-
son-Welsley Publishing Company, 1997. [5] DELANNOY (C.). Programmer en langage [7] Revue spcialise : The C/C++ Users Journal
[3] STROUSTRUP (B.). Le langage C++, Troi- C++, cinquime dition. ditions Eyrolles, 61 (advanced solutions for C/C++ program-
sime dition. CampusPress France, 1999. boulevard St Germain 75240 Paris, 2002. mers). Site internet : http://www.cuj.com

Toute reproduction sans autorisation du Centre franais dexploitation du droit de copie est strictement interdite.
S 8 065 18 Techniques de lIngnieur, trait Informatique industrielle

You might also like