Vous êtes sur la page 1sur 468

CoursdeC/C++

ChristianCasteyde

CoursdeC/C++
parChristianCasteyde
Copyright2003ChristianCasteyde
Permissionisgrantedtocopy,distributeand/ormodifythisdocumentunderthetermsoftheGNUFreeDocumentationLicense,Version1.1
oranylaterversionpublishedbytheFreeSoftwareFoundation;withnoInvariantSections,withnoFrontCoverTexts,andwithno
BackCoverTexts.
Acopyofthelicenseisincludedinthesectionentitled"GNUFreeDocumentationLicense".

Permissionvousestdonnedecopier,distribueretmodifiercedocumentselonlestermesdelalicenceGNUpourlesdocumentationslibres,
version1.1outouteautreversionultrieurepublieparlaFreeSoftwareFoundation.
Unecopiedecettelicenceestinclusedanslannexeintitule"GNUFreeDocumentationLicense".Voustrouverezgalementunetraduction
nonofficielledecettelicencedanslannexeintitule"LicencededocumentationlibreGNU".

Historiquedesversions

Version1.40.5 14/06/2002 Revupar:CC


Correctiondelallocationdynamiquedetableauxplusdunedimension.
Version1.40.4 21/09/2002 Revupar:CC
Correctiondelexemplederecherchesurleschanesdecaractres.AjoutdesinitialiseursC99.Prcisionssurlaportabilitdestyp
Version1.40.3 12/05/2002 Revupar:CC
Nombreusescorrectionsorthographiques.Quelquescorrectionsetprcisions.Clarificationdequelquesexemples.
Version1.40.2 26/01/2001 Revupar:CC
Correctionsorthographiques.AjoutdunliensurlesspcificationsSingleUnixdelOpenGroup.
Version1.40.1 09/09/2001 Revupar:CC
Correctionsorthographiques.Prcisionssurlesoptimisationsdesoprateursdincrmentationetdedcrmentationpostfixsetpr
Version1.40.0 30/07/2001 Revupar:CC
Versionfinale.Rorganisationpartielledelapremirepartie.Scissionduchapitrecontenantlesstructuresdecontrleetlesdfini
Version1.39.99 24/06/2001 Revupar:CC
Descriptiondeslocalesstandards.Prcisionsurlinitialisationdesvariableslorsdeleursdclarations.Prcisionsurlesdroitsdacc
Version1.39.4 27/05/2001 Revupar:CC
Descriptiondesfluxdentre/sortiedelabibliothquestandard.Modificationdelaprsentationsommairedesfluxdanslechapitr
Version1.39.3 03/05/2001 Revupar:CC
Descriptiondesalgorithmesdelabibliothquestandard.
Version1.39.2 22/04/2001 Revupar:CC
Descriptiondesconteneursdelabibliothquestandard.AjoutdunetraductiondelalicenceFDL.Suppressiondessymboles&colo
Version1.39.1 05/03/2001 Revupar:CC
DescriptiondestypesdedonnescomplmentairesdelabibliothquestandardC++.Correctionducomportementdubloccatchde
Version1.39.0 04/02/2001 Revupar:CC
MiseenconformitdesenttesC++desexemplesaveclanorme.Correctiondesexemplesutilisantdesnomsrservsparlabibli
Version1.38.1 14/10/2000 Revupar:CC
Prcisionssurlesclassesdebasevirtuelles.Correctionsorthographiques.
Version1.38.0 01/10/2000 Revupar:CC
Correctionstypographiques.Prcisionssurlesoprateurs&et*.
Version1.37
23/08/2000 Revupar:CC
PassageauformatdefichierSGML.Ajoutdeslienshypertextes.Correctionsmineures.
Version1.36
27/07/2000 Revupar:CC
Complmentsurlesparenthsesdanslesdfinitionsdemacros.Correctionssurlanumrotationdesparagraphes.
Version1.35
10/07/2000 Revupar:CC
Correctionssurlesdclarationsusing.
Version1.34
09/07/2000 Revupar:CC
PassageenlicenceFDL.Ajoutdelatabledesmatires.
Version1.33
22/60/2000 Revupar:CC
Correctionduneerreurdansleparagraphesurlesparamtrestemplatetemplate.Correctionsorthographiquesdiverses.

Version1.32
17/06/2000/ Revupar:CC
Correctionduneerreurdansleprogrammedexempledupremierchapitre.Correctionduneerreurdansunexemplesurlad rivat
Version1.31
12/02/2000 Revupar:CC
Correctionsmineurs.Ajoutduparagraphesurlaspcialisationdunefonctionmembreduneclassetemplate.
Version1.30
05/12/1999 Revupar:CC
Ajoutdelalicence.Modificationsmineuresduformatage.
Version <1.30 <1998
Revupar:CC
Versioninitiale.

Tabledesmatires

Avantpropos.........................................................................................................................

I.LelangageC++....................................................................................................................

1.PremireapprocheduC/C++..............................................................................................
1.1.LescommentairesenC++........................................................................................
1.2.LestypesprdfinisduC/C++...................................................................................2
1.3.Notationdesvaleurs...............................................................................................
1.4.Ladfinitiondesvariables.......................................................................................
1.5.Instructionsetoprations..........................................................................................
1.6.Lesfonctions.......................................................................................................
1.6.1.Dfinitiondesfonctions...............................................................................12
1.6.2.Appeldesfonctions......................................................................................13
1.6.3.Dclarationdesfonctions.............................................................................13
1.6.4.Surchargedesfonctions...............................................................................14
1.6.5.Fonctionsinline............................................................................................
1.6.6.Fonctionsstatiques.......................................................................................1
1.6.7.Fonctionsprenantunnombrevariabledeparamtres.................................16
1.7.Lafonctionmain.......................................................................................................18
1.8.Lesfonctionsdentre/sortiedebase.....................................................................19
1.8.1.Gnralitssurlesfluxdentre/sortieenC..............................................19
1.8.2.Lafonctionprintf.........................................................................................2
1.8.3.Lafonctionscanf..........................................................................................23
1.9.Exempledeprogrammecomplet..............................................................................24
2.Lesstructuresdecontrle...................................................................................................
2.1.Lastructureconditionnelleif....................................................................................25
2.2.Labouclefor........................................................................................................
2.3.Lewhile.............................................................................................................
2.4.Ledo.................................................................................................................
2.5.Lebranchementconditionnel...................................................................................28
2.6.Lesaut...............................................................................................................
2.7.Lescommandesderupturedesquence..................................................................29
3.Typesavancsetclassesdestockage....................................................................................3
3.1.Structuresdedonnesettypescomplexes................................................................31
3.1.1.Lesstructures...............................................................................................
3.1.2.Lesunions.................................................................................................
3.1.3.Lesnumrations.........................................................................................3
3.1.4.Leschampsdebits.......................................................................................3
3.1.5.Initialisationdesstructuresetdestableaux..................................................36
3.1.6.Lesaliasdetypes.........................................................................................3
3.1.7.Transtypages...............................................................................................
3.2.Lesclassesdestockage............................................................................................
4.Lespointeursetrfrences................................................................................................
4.1.Notiondadresse...................................................................................................
4.2.Notiondepointeur.................................................................................................
4.3.Drfrencement,indirection...................................................................................44
4.4.Notionderfrence.................................................................................................
4.5.Lienentrelespointeursetlesrfrences..................................................................46
4.6.Passagedeparamtresparvariableouparvaleur....................................................47
4.6.1.Passageparvaleur........................................................................................
4.6.2.Passageparvariable.....................................................................................4

4.6.3.Avantagesetinconvnientsdesdeuxmthodes...........................................48
4.6.4.CommentpasserlesparamtresparvariableenC?....................................49
4.6.5.Passagedeparamtresparrfrence............................................................49
4.7.Rfrencesetpointeursconstantsetvolatiles..........................................................51
4.8.Arithmtiquedespointeurs.......................................................................................54
4.9.Utilisationdespointeursaveclestableaux...............................................................55
4.9.1.Conversionsdestableauxenpointeurs........................................................55
4.9.2.Paramtresdefonctiondetypetableau.......................................................56
4.10.Leschanesdecaractres:pointeursettableauxlafois!...................................57
4.11.Allocationdynamiquedemmoire........................................................................58
4.11.1.AllocationdynamiquedemmoireenC...................................................58
4.11.2.AllocationdynamiqueenC++...................................................................63
4.12.Pointeursetrfrencesdefonctions.......................................................................65
4.12.1.Pointeursdefonctions................................................................................65
4.12.2.Rfrencesdefonctions.............................................................................67
4.13.Paramtresdelafonctionmainlignedecommande............................................68
4.14.DANGER.........................................................................................................
5.LeprprocesseurC.........................................................................................................
5.1.Dfinition...........................................................................................................
5.2.Lescommandesduprprocesseur............................................................................71
5.2.1.Inclusiondefichier.......................................................................................
5.2.2.Constantesdecompilationetremplacementdetexte..................................72
5.2.3.Compilationconditionnelle..........................................................................73
5.2.4.Autrescommandes.......................................................................................7
5.3.Lesmacros..........................................................................................................
5.4.Manipulationdechanesdecaractresdanslesmacros...........................................76
5.5.Lestrigraphes.......................................................................................................
6.Modularitdesprogrammesetgnrationdesbinaires........................................................79
6.1.Pourquoifaireuneprogrammationmodulaire?.......................................................79
6.2.Lesdiffrentesphasesduprocessusdegnrationdesexcutables.........................79
6.3.CompilationspareenC/C++................................................................................82
6.4.Syntaxedesoutilsdecompilation............................................................................83
6.4.1.Syntaxedescompilateurs.............................................................................83
6.4.2.Syntaxedemake..........................................................................................
6.5.Problmessyntaxiquesrelatifslacompilationspare.........................................85
6.5.1.Dclarationdestypes...................................................................................85
6.5.2.Dclarationdesvariables.............................................................................86
6.5.3.Dclarationdesfonctions.............................................................................86
6.5.4.Directivesdditiondeliens........................................................................86
7.Commentfaireducodeillisible?.........................................................................................8
8.C++:lacoucheobjet.......................................................................................................
8.1.Gnralits..........................................................................................................
8.2.ExtensiondelanotiondetypeduC.........................................................................92
8.3.DclarationdeclassesenC++..................................................................................9
8.4.Encapsulationdesdonnes.......................................................................................9
8.5.Hritage.............................................................................................................
8.6.Classesvirtuelles...................................................................................................
8.7.Fonctionsetclassesamies......................................................................................1
8.7.1.Fonctionsamies.........................................................................................1
8.7.2.Classesamies.............................................................................................1
8.8.Constructeursetdestructeurs..................................................................................10
8.8.1.Dfinitiondesconstructeursetdesdestructeurs........................................104

vi

8.8.2.Constructeursdecopie...............................................................................109
8.8.3.Utilisationdesconstructeursdanslestranstypages...................................110
8.9.Pointeurthis.........................................................................................................
8.10.Donnesetfonctionsmembresstatiques..............................................................112
8.10.1.Donnesmembresstatiques.....................................................................112
8.10.2.Fonctionsmembresstatiques...................................................................113
8.11.Surchargedesoprateurs......................................................................................1
8.11.1.Surchargedesoprateursinternes............................................................115
8.11.2.Surchargedesoprateursexternes...........................................................118
8.11.3.Oprateursdaffectation...........................................................................120
8.11.4.Oprateursdetranstypage........................................................................122
8.11.5.Oprateursdecomparaison......................................................................122
8.11.6.Oprateursdincrmentationetdedcrmentation.................................123
8.11.7.Oprateurfonctionnel..............................................................................123
8.11.8.Oprateursdindirectionetdedrfrencement......................................126
8.11.9.Oprateursdallocationdynamiquedemmoire.....................................127
8.12.Desentressortiessimplifies...........................................................................133
8.13.Mthodesvirtuelles..............................................................................................
8.14.Drivation.........................................................................................................
8.15.MthodesvirtuellespuresClassesabstraites.....................................................140
8.16.Pointeurssurlesmembresduneclasse...............................................................145
9.LesexceptionsenC++.......................................................................................................
9.1.Lancementetrcuprationduneexception...........................................................150
9.2.Remontedesexceptions........................................................................................1
9.3.Listedesexceptionsautorisespourunefonction.................................................154
9.4.Hirarchiedesexceptions.......................................................................................15
9.5.Exceptionsdanslesconstructeurs..........................................................................157
10.Identificationdynamiquedestypes...................................................................................1
10.1.Identificationdynamiquedestypes......................................................................161
10.1.1.Loprateurtypeid....................................................................................16
10.1.2.Laclassetype_info..................................................................................16
10.2.TranstypagesC++................................................................................................
10.2.1.Transtypagedynamique...........................................................................164
10.2.2.Transtypagestatique................................................................................16
10.2.3.Transtypagedeconstanceetdevolatilit.................................................167
10.2.4.Rinterprtationdesdonnes...................................................................167
11.Lesespacesdenommage.................................................................................................
11.1.Dfinitiondesespacesdenommage.....................................................................169
11.1.1.Espacesdenommagenommes...............................................................169
11.1.2.Espacesdenommageanonymes..............................................................171
11.1.3.Aliasdespacesdenommage...................................................................172
11.2.Dclarationusing.................................................................................................
11.2.1.Syntaxedesdclarationsusing................................................................172
11.2.2.Utilisationdesdclarationsusingdanslesclasses..................................174
11.3.Directiveusing....................................................................................................
12.Lestemplate................................................................................................................
12.1.Gnralits.........................................................................................................
12.2.Dclarationdesparamtrestemplate....................................................................179
12.2.1.Dclarationdestypestemplate................................................................179
12.2.2.Dclarationdesconstantestemplate........................................................180
12.3.Fonctionsetclassestemplate................................................................................18
12.3.1.Fonctionstemplate...................................................................................18

vii

12.3.2.Lesclassestemplate.................................................................................182
12.3.3.Fonctionsmembrestemplate...................................................................185
12.4.Instanciationdestemplate....................................................................................18
12.4.1.Instanciationimplicite..............................................................................188
12.4.2.Instanciationexplicite..............................................................................189
12.4.3.Problmessoulevsparlinstanciationdestemplate...............................190
12.5.Spcialisationdestemplate...................................................................................191
12.5.1.Spcialisationtotale.................................................................................191
12.5.2.Spcialisationpartielle.............................................................................192
12.5.3.Spcialisationdunemthodeduneclassetemplate...............................194
12.6.Motcltypename.................................................................................................
12.7.Fonctionsexportes..............................................................................................

II.LabibliothquestandardC++.................................................................................................

13.Servicesetnotionsdebasedelabibliothquestandard...................................................199
13.1.EncapsulationdelabibliothqueCstandard........................................................199
13.2.Dfinitiondesexceptionsstandards.....................................................................201
13.3.Abstractiondestypesdedonnes:lestraits........................................................204
13.4.Abstractiondespointeurs:lesitrateurs..............................................................206
13.4.1.Notionsdebaseetdfinition....................................................................206
13.4.2.Classificationdesitrateurs......................................................................207
13.4.3.Itrateursadaptateurs...............................................................................209
13.4.3.1.Adaptateurspourlesfluxdentre/sortiestandards..................210
13.4.3.2.Adaptateurspourlinsertiondlmentsdanslesconteneurs.....212
13.4.3.3.Itrateurinversepourlesitrateursbidirectionnels.....................215
13.5.Abstractiondesfonctions:lesfoncteurs..............................................................217
13.5.1.Foncteursprdfinis.................................................................................217
13.5.2.Prdicatsetfoncteursdoprateurslogiques............................................222
13.5.3.Foncteursrducteurs................................................................................22
13.6.Gestionpersonnalisedelammoire:lesallocateurs.........................................225
13.7.Notiondecomplexitalgorithmique....................................................................229
13.7.1.Gnralits...............................................................................................
13.7.2.Notionsmathmatiquesdebaseetdfinition...........................................230
13.7.3.Interprtationpratiquedelacomplexit..................................................231
14.Lestypescomplmentaires...............................................................................................
14.1.Leschanesdecaractres......................................................................................233
14.1.1.Constructionetinitialisationdunechane..............................................237
14.1.2.Accsauxpropritsdunechane..........................................................238
14.1.3.Modificationdelatailledeschanes........................................................239
14.1.4.Accsauxdonnesdelachanedecaractres.........................................240
14.1.5.Oprationssurleschanes........................................................................242
14.1.5.1.Affectationetconcatnationdechanesdecaractres................242
14.1.5.2.Extractiondedonnesdunechanedecaractres......................244
14.1.5.3.Insertionetsuppressiondecaractresdansunechane...............245
14.1.5.4.Remplacementsdecaractresdunechane................................246
14.1.6.Comparaisondechanesdecaractres.....................................................248
14.1.7.Recherchedansleschanes......................................................................249
14.1.8.Fonctionsdentre/sortiedeschanesdecaractres...............................251
14.2.Lestypesutilitaires...............................................................................................
14.2.1.Lespointeursauto....................................................................................25
14.2.2.Lespaires.................................................................................................
14.3.Lestypesnumriques...........................................................................................2

viii

14.3.1.Lescomplexes..........................................................................................257
14.3.1.1.Dfinitionetprincipalespropritsdesnombrescomplexes......257
14.3.1.2.Laclassecomplex.......................................................................259
14.3.2.Lestableauxdevaleurs............................................................................262
14.3.2.1.Fonctionnalitsdebasedesvalarray...........................................263
14.3.2.2.Slectionmultipledeslmentsdunvalarray............................267
14.3.2.2.1.Slectionparunmasque.................................................267
14.3.2.2.2.Slectionparindexationexplicite...................................268
14.3.2.2.3.Slectionparindexationimplicite..................................269
14.3.2.2.4.Oprationsralisablessurlesslectionsmultiples.........271
14.3.3.Leschampsdebits...................................................................................27
15.Lesfluxdentre/sortie..................................................................................................
15.1.Notionsdebaseetprsentationgnrale..............................................................277
15.2.Lestampons.......................................................................................................
15.2.1.Gnralitssurlestampons.....................................................................279
15.2.2.Laclassebasic_streambuf........................................................................280
15.2.3.Lesclassesdetamponsbasic_streambufetbasic_filebuf........................285
15.2.3.1.Laclassebasic_stringbuf.............................................................286
15.2.3.2.Laclassebasic_filebuf.................................................................288
15.3.Lesclassesdebasedesflux:ios_baseetbasic_ios.............................................289
15.3.1.Laclasseios_base....................................................................................29
15.3.2.Laclassebasic_ios...................................................................................29
15.4.Lesfluxdentre/sortie.......................................................................................29
15.4.1.Laclassedebasebasic_ostream..............................................................299
15.4.2.Laclassedebasebasic_istream...............................................................305
15.4.3.Laclassebasic_iostream..........................................................................311
15.5.Lesfluxdentre/sortiesurchanesdecaractres..............................................312
15.6.Lesfluxdentre/sortiesurfichiers....................................................................313
16.Leslocales..................................................................................................................
16.1.Notionsdebaseetprincipedefonctionnementdesfacettes................................318
16.2.Lesfacettesstandards...........................................................................................3
16.2.1.Gnralits...............................................................................................
16.2.2.Lesfacettesdemanipulationdescaractres............................................324
16.2.2.1.Lafacettectype...........................................................................324
16.2.2.2.Lafacettecodecvt........................................................................328
16.2.3.Lesfacettesdecomparaisondechanes...................................................332
16.2.4.Lesfacettesdegestiondesnombres........................................................335
16.2.4.1.Lafacettenum_punct..................................................................335
16.2.4.2.Lafacettedcrituredesnombres...............................................337
16.2.4.3.Lafacettedelecturedesnombres...............................................338
16.2.5.Lesfacettesdegestiondesmonnaies.......................................................339
16.2.5.1.Lafacettemoney_punct..............................................................340
16.2.5.2.Lesfacettesdelectureetdcrituredesmontants.......................342
16.2.6.Lesfacettesdegestiondutemps..............................................................343
16.2.6.1.Lafacettedcrituredesdates.....................................................345
16.2.6.2.Lafacettedelecturedesdates.....................................................345
16.2.7.Lesfacettesdegestiondesmessages.......................................................347
16.3.Personnalisationdesmcanismesdelocalisation.................................................349
16.3.1.Crationetintgrationdunenouvellefacette.........................................349
16.3.2.Remplacementdunefacetteexistante.....................................................353
17.Lesconteneurs.............................................................................................................
17.1.Fonctionnalitsgnralesdesconteneurs.............................................................357

ix

17.1.1.Dfinitiondesitrateurs...........................................................................358
17.1.2.Dfinitiondestypesdedonnesrelatifsauxobjetscontenus..................359
17.1.3.Spcificationdelallocateurmmoireutiliser.......................................359
17.1.4.Oprateursdecomparaisondesconteneurs.............................................360
17.1.5.Mthodesdintrtgnral......................................................................361
17.2.Lessquences.....................................................................................................
17.2.1.Fonctionnalitscommunes.......................................................................361
17.2.1.1.Constructionetinitialisation.......................................................361
17.2.1.2.Ajoutetsuppressiondlments.................................................363
17.2.2.Lesdiffrentstypesdesquences............................................................364
17.2.2.1.Leslistes......................................................................................3
17.2.2.2.Lesvecteurs.................................................................................368
17.2.2.3.Lesdeques...................................................................................37
17.2.2.4.Lesadaptateursdesquences......................................................371
17.2.2.4.1.Lespiles..........................................................................371
17.2.2.4.2.Lesfiles...........................................................................372
17.2.2.4.3.Lesfilesdepriorits........................................................372
17.3.Lesconteneursassociatifs....................................................................................37
17.3.1.Gnralitsetpropritsdebasedesclefs...............................................375
17.3.2.Constructionetinitialisation....................................................................376
17.3.3.Ajoutetsuppressiondlments..............................................................377
17.3.4.Fonctionsderecherche............................................................................379
18.Lesalgorithmes.............................................................................................................
18.1.Oprationsgnralesdemanipulationdesdonnes.............................................385
18.1.1.Oprationsdinitialisationetderemplissage...........................................386
18.1.2.Oprationsdecopie..................................................................................387
18.1.3.Oprationsdchangedlments............................................................388
18.1.4.Oprationsdesuppressiondlments.....................................................389
18.1.5.Oprationsderemplacement....................................................................391
18.1.6.Rorganisationdesquences...................................................................392
18.1.6.1.Oprationsderotationetdepermutation....................................393
18.1.6.2.Oprationsdinversion................................................................394
18.1.6.3.Oprationsdemlange................................................................395
18.1.7.Algorithmesditrationetdetransformation...........................................396
18.2.Oprationsderecherche.......................................................................................40
18.2.1.Oprationderecherchedlments..........................................................401
18.2.2.Oprationsderecherchedemotifs...........................................................403
18.3.Oprationsdordonnancement..............................................................................405
18.3.1.Oprationsdegestiondestas...................................................................406
18.3.2.Oprationsdetri.......................................................................................4
18.3.3.Oprationsderecherchebinaire...............................................................412
18.4.Oprationsdecomparaison..................................................................................41
18.5.Oprationsensemblistes.......................................................................................41
18.5.1.Oprationsdinclusion.............................................................................417
18.5.2.Oprationsdintersection.........................................................................418
18.5.3.Oprationsdunionetdefusion...............................................................420
18.5.4.Oprationsdediffrence..........................................................................422
18.5.5.Oprationsdepartitionnement.................................................................424

19.Conclusion........................................................................................................................
A.Prioritsdesoprateurs.............................................................................................................429

B.DraftPapers.......................................................................................................................

C.GNUFreeDocumentationLicense...........................................................................................4

D.LicencededocumentationlibreGNU......................................................................................4

BIBLIOGRAPHIE..................................................................................................................

xi

xii

Listedestableaux

11.Typespourleschanesdeformatde printf..............................................................................21
12.Optionspourlestypesdeschanesdeformat.............................................................................22
21.Oprateursdecomparaison.....................................................................................................
22.Oprateurslogiques..............................................................................................................
51.Trigraphes.......................................................................................................................
81.Droitsdaccssurlesmembreshrits.......................................................................................9
141.Fonctionsderecherchedansleschanesdecaractres...........................................................249
142.Fonctionsspcifiquesauxcomplexes......................................................................................2
151.Optionsdeformatagedesflux................................................................................................
152.Modesdouverturedesfichiers...............................................................................................
153.Directionsdedplacementdansunfichier..............................................................................293
154.tatsdesfluxdentre/sortie.................................................................................................
155.Manipulateursdesfluxdesortie..............................................................................................
156.Manipulateursutilisantdesparamtres...................................................................................30
157.Manipulateursdesfluxdentre..............................................................................................
161.FonctionsCdegestiondesdates.............................................................................................
171.Mthodesspcifiquesauxlistes..............................................................................................
A1.Oprateursdulangage..........................................................................................................

Listedesillustrations

41.Notiondepointeuretdadresse................................................................................................
61.Processusdegnrationdesbinaires...........................................................................................80

Listedesexemples

11.CommentaireC...................................................................................................................
12.CommentaireC++................................................................................................................
13.Typessignsetnonsigns......................................................................................................
14.Notationdesentiersenbase10.................................................................................................
15.Notationdesentiersenbase16.................................................................................................
16.Notationdesentiersenbase8...................................................................................................
17.Notationdesrels................................................................................................................
18.Dfinitiondevariables..........................................................................................................
19.Dfinitionduntableau.........................................................................................................
110.Instructionvide.................................................................................................................
111.Affectationcompose.........................................................................................................
112.Instructioncompose..........................................................................................................
113.Dfinitiondefonction.........................................................................................................
114.Dfinitiondeprocdure........................................................................................................
115.Appeldefonction...............................................................................................................
116.Dclarationdefonction.........................................................................................................
117.Surchargedefonctions.........................................................................................................
118.Fonctioninline.................................................................................................................
119.Fonctionstatique................................................................................................................
120.Fonctionnombredeparamtresvariable................................................................................18
121.Programmeminimal...........................................................................................................

xiii

122.Utilisationdeprintfetfprintf.................................................................................................
123.Programmecompletsimple....................................................................................................
21.Testconditionnelif...............................................................................................................
22.Bouclefor........................................................................................................................
23.Bouclewhile.....................................................................................................................
24.Boucledo.........................................................................................................................
25.Branchementconditionnelswitch...............................................................................................
26.Rupturedesquenceparcontinue..............................................................................................
31.Dclarationdevariabledetypestructure....................................................................................3
32.Dclarationdestructure...............................................................................................................32
33.Dclarationduneunion.........................................................................................................
34.Unionavecdiscriminant........................................................................................................
35.Dclarationdunenumration.................................................................................................
36.Dclarationdunchampsdebits...............................................................................................
37.Initialisationdunestructure....................................................................................................
38.InitialisationdestructureC99...................................................................................................
39.Dfinitiondetypesimple.......................................................................................................
310.Dfinitiondetypetableau..........................................................................................................37
311.Dfinitiondetypestructure.....................................................................................................
312.TranstypageenC...............................................................................................................
313.Dclarationdunevariablelocalestatique................................................................................40
314.Dclarationdunevariableconstante........................................................................................
315.Dclarationdeconstanteexternes.............................................................................................
316.Utilisationdumotclmutable.................................................................................................
41.Dclarationdepointeurs........................................................................................................
42.Utilisationdepointeursdestructures..........................................................................................
43.Dclarationderfrences.......................................................................................................
44.Passagedeparamtreparvaleur................................................................................................
45.PassagedeparamtreparvariableenPascal...............................................................................4
46.PassagedeparamtreparvariableenC......................................................................................4
47.PassagedeparamtreparrfrenceenC++................................................................................50
48.Passagedeparamtresconstantparrfrence.............................................................................50
49.Crationdunobjettemporairelorsdunpassageparrfrence.................................................50
410.Arithmtiquedespointeurs.....................................................................................................
411.Accsauxlmentsduntableauparpointeurs........................................................................56
412.Passagedetableauenparamtre...............................................................................................
413.AllocationdynamiquedemmoireenC...................................................................................59
414.Dclarationdepointeurdefonction..........................................................................................
415.Drfrencementdepointeurdefonction.................................................................................66
416.Applicationdespointeursdefonctions.....................................................................................6
417.Rcuprationdelalignedecommande.....................................................................................
51.Dfinitiondeconstantesdecompilation.....................................................................................7
52.MacrosMINetMAX...........................................................................................................
61.Compilationdunfichieretditiondeliens................................................................................84
62.Fichiermakefilesansdpendances............................................................................................
63.Fichiermakefileavecdpendances.............................................................................................
64.DclarationsutilisablesenCetenC++......................................................................................8
71.Programmeparfaitementillisible...............................................................................................
81.Dclarationdemthodesdeclasse.............................................................................................
82.Oprateurdersolutiondeporte...............................................................................................
83.Utilisationdeschampsduneclassedansunedesesmthodes..................................................94
84.Utilisationdumotclclass.....................................................................................................

xiv

85.Hritagepublic,privetprotg...............................................................................................
86.Oprateurdersolutiondeporteetmembredeclassesdebase..............................................100
87.Classesvirtuelles.................................................................................................................
88.Fonctionsamies..................................................................................................................
89.Classeamie.......................................................................................................................
810.Constructeursetdestructeurs...................................................................................................105
811.Appelduconstructeurdesclassesdebase..............................................................................106
812.Initialisationdedonnesmembresconstantes.........................................................................108
813.Donnemembrestatique.......................................................................................................
814.Fonctionmembrestatique.....................................................................................................
815.Appeldefonctionmembrestatique.........................................................................................114
816.Surchargedesoprateursinternes...........................................................................................1
817.Surchargedoprateursexternes..............................................................................................
818.Oprateursdincrmentationetdedcrmentation.................................................................123
819.Implmentationduneclassematrice......................................................................................1
820.Oprateurdedrfrencementetdindirection.......................................................................126
821.Dterminationdelatailledelenttedestableaux................................................................127
822.Oprateursnewavecplacement..............................................................................................
823.Utilisationdenewsansexception...........................................................................................1
824.Fluxdentre/sortiecinetcout..............................................................................................
825.Redfinitiondemthodedeclassedebase.............................................................................136
826.Conteneurdobjetspolymorphiques.......................................................................................14
827.Pointeurssurmembresstatiques.............................................................................................1
91.Utilisationdesexceptions......................................................................................................
92.Installationdungestionnairedexceptionavecset_terminate..................................................153
93.Gestiondelalistedesexceptionsautorises.............................................................................155
94.Classificationdesexceptions....................................................................................................
95.Exceptionsdanslesconstructeurs.............................................................................................1
101.Oprateurtypeid................................................................................................................
102.Oprateurdynamic_cast.......................................................................................................
111.Extensiondenamespace......................................................................................................
112.Accsauxmembresdunnamespace......................................................................................1
113.Dfinitionexternedunefonctiondenamespace....................................................................170
114.Dfinitiondenamespacedansunnamespace..........................................................................170
115.Dfinitiondenamespaceanonyme..........................................................................................1
116.Ambigutsentrenamespaces.................................................................................................
117.Dclarationusing...............................................................................................................
118.Dclarationsusingmultiples...................................................................................................
119.Extensiondenamespaceaprsunedclarationusing.............................................................173
1110.Conflitentredclarationsusingetidentificateurslocaux......................................................174
1111.Dclarationusingdansuneclasse.........................................................................................1
1112.Rtablissementdedroitsdaccslaidedunedirectiveusing...........................................175
1113.Directiveusing................................................................................................................
1114.Extensiondenamespaceaprsunedirectiveusing...............................................................176
1115.Conflitentredirectiveusingetidentificateurslocaux...........................................................177
121.Dclarationdeparamtrestemplate........................................................................................1
122.Dclarationdeparamtretemplatetemplate...........................................................................180
123.Dclarationdeparamtrestemplatedetypeconstante...........................................................181
124.Dfinitiondefonctiontemplate..............................................................................................
125.Dfinitiondunepiletemplate................................................................................................
126.Fonctionmembretemplate.....................................................................................................
127.Fonctionmembretemplateduneclassetemplate..................................................................186

xv

128.Fonctionmembretemplateetfonctionmembrevirtuelle.......................................................187
129.Surchargedefonctionmembreparunefonctionmembretemplate........................................187
1210.Instanciationimplicitedefonctiontemplate.........................................................................188
1211.Instanciationexplicitedeclassetemplate.............................................................................190
1212.Spcialisationtotale..........................................................................................................
1213.Spcialisationpartielle.......................................................................................................
1214.Spcialisationdefonctionmembredeclassetemplate.........................................................194
1215.Motcltypename.............................................................................................................
1216.Motclexport.................................................................................................................
131.Dterminationdeslimitesduntype.......................................................................................20
132.Itrateursdefluxdentre......................................................................................................
133.Itrateurdefluxdesortie......................................................................................................
134.Itrateurdinsertion.............................................................................................................
135.Utilisationdunitrateurinverse.............................................................................................2
136.Utilisationdesfoncteursprdfinis.........................................................................................2
137.Adaptateursdefonctions.......................................................................................................
138.Rductiondefoncteursbinaires..............................................................................................
139.Utilisationdelallocateurstandard..........................................................................................227
141.Redimensionnementdunechane...........................................................................................239
142.Rservationdemmoiredansunechane...............................................................................240
143.Accsdirectauxdonnesdunechane...................................................................................2
144.Affectationdechanedecaractres.........................................................................................
145.Concatnationdechanesdecarctres....................................................................................24
146.Copiedetravaildesdonnesdunebasic_string.....................................................................244
147.Extractiondesouschane......................................................................................................
148.Insertiondecaractresdansunechane..................................................................................24
149.Suppressiondecaractresdansunechane.............................................................................246
1410.Remplacementdunesouschanedansunechane..............................................................247
1411.changeducontenudedeuxchanesdecaractres..............................................................247
1412.Comparaisonsdechanesdecaractres.................................................................................248
1413.Recherchesdansleschanesdecaractres............................................................................250
1414.Lecturedelignessurlefluxdentre....................................................................................25
1415.Utilisationdespointeursautomatiques..................................................................................253
1416.Sortiedunpointeurdunauto_ptr........................................................................................2
1417.Utilisationdespaires.........................................................................................................
1418.Manipulationdesnombrescomplexes..................................................................................26
1419.Modificationdelatailledunvalarray..................................................................................26
1420.Oprationssurlesvalarray...................................................................................................
1421.Dcalagesetrotationsdevaleurs..........................................................................................2
1422.Slectiondeslmentsdunvalarrayparunmasque............................................................268
1423.Slectiondeslmentsdunvalarrayparindexation............................................................269
1424.Slectionparindexationimplicite.........................................................................................2
1425.Utilisationdunbitset.........................................................................................................
1426.Manipulationdesbitsdunchampdebits.............................................................................275
151.Lectureetcrituredansuntampondechanedecaractres...................................................287
152.Lectureetcrituredansuntampondefichier.........................................................................289
153.Modificationdesoptionsdeformatagedesflux......................................................................295
154.Dfinitiondunnouveloprateurdinsertionpourunfluxdesortie.......................................301
155.criturededonnesbrutessurunfluxdesortie......................................................................302
156.Utilisationdesmanipulateurssurunfluxdesortie.................................................................305
157.crituredunnouveloprateurdextractionpourunfluxdentre.........................................307
158.Lecturesdelignessurlefluxdentrestandard......................................................................310

xvi

159.Utilisationdefluxdentre/sortiesurchanesdecaractres.................................................313
1510.Utilisationdefluxdentre/sortiesurunfichier..................................................................314
1511.Repositionnementdupointeurdefichierdansunfluxdentre/sortie................................315
161.ProgrammeC++prenantencomptelalocaledelenvironnement.........................................322
162.Conversiondunewstringenstring.........................................................................................
163.Conversiondunechanedecaractreslargesenchaneencodagevariable........................330
164.Dterminationdelalongueurdunechanedecaractresencodagevariable......................331
165.Comparaisondechanesdecaractreslocalises....................................................................334
166.Dfinitiondenouvellesfacettes...............................................................................................349
167.Spcialisationdunefacetteexistante......................................................................................3
171.Constructionetinitialisationduneliste..................................................................................36
172.Insertiondlmentsdansuneliste.........................................................................................3
173.Accslatteetlaqueueduneliste...................................................................................36
174.Manipulationdelistes.........................................................................................................
175.Accsauxlmentsdunvecteur............................................................................................
176.Utilisationdunepile...........................................................................................................
177.Utilisationdunefile...........................................................................................................
178.Utilisationdunefiledepriorit..............................................................................................
179.Constructionetinitialisationduneassociationsimple...........................................................376
1710.Insertionetsuppressiondlmentsduneassociation..........................................................378
1711.Recherchedansuneassociation............................................................................................
1712.Utilisationdunfoncteurdecomparaisonpersonnalis........................................................381
1713.Dfinitiondirectedufoncteurdecomparaisonpourlesrecherches.....................................382
181.Algorithmedegnrationdobjetsetderemplissagedunconteneur....................................386
182.Algorithmedecopieinverse..................................................................................................
183.Algorithmedchange.........................................................................................................
184.Algorithmedesuppression.....................................................................................................
185.Algorithmedesuppressiondesdoublons................................................................................39
186.Algorithmederechercheetderemplacement.........................................................................392
187.Algorithmederotation.........................................................................................................
188.Algorithmedepermutation.....................................................................................................
189.Algorithmedinversion............................................................................................................395
1810.Algorithmedemlange.......................................................................................................
1811.Algorithmesditration.......................................................................................................
1812.Algorithmededcomptedlments.....................................................................................3
1813.Algorithmedaccumulation..................................................................................................
1814.Algorithmedeproduitscalaire..............................................................................................
1815.Algorithmesdesommespartiellesetdediffrencesadjacentes...........................................401
1816.Algorithmederecherchedlments.....................................................................................4
1817.Algorithmesderecherchedemotif.......................................................................................40
1818.Algorithmederecherchededoublons...................................................................................4
1819.Algorithmesdemanipulationdestas....................................................................................40
1820.Algorithmedetri..............................................................................................................
1821.Algorithmedetripartiel.......................................................................................................
1822.Algorithmedepositionnementdunimelment.................................................................411
1823.Algorithmesdedterminationdumaximumetduminimum...............................................411
1824.Algorithmesdedterminationdesbornesinfrieuresetsuprieures....................................413
1825.Algorithmederecherchebinaire...........................................................................................4
1826.Algorithmedecomparaisondeconteneurs...........................................................................416
1827.Algorithmedecomparaisonlexicographique........................................................................417
1828.Algorithmededterminationdinclusion..............................................................................418
1829.Algorithmedintersectiondensembles.................................................................................419

xvii

1830.Algorithmesdunionetdefusiondensembles.....................................................................420
1831.Algorithmederunificationdedeuxsousensembles...........................................................421
1832.Algorithmesdediffrencedensembles................................................................................42
1833.Algorithmedepartitionnement.............................................................................................4

xviii

Avantpropos
CelivreestuncoursdeCetdeC++.
Ilsadresseauxpersonnesquiontdjquelquesnotionsde
programmationdansunlangagequelconque. Lesconnaissancesrequisesnesont pastrsleves
cependant:ilnestpasncessairedavoirfaitdegrandsprogrammespourlirecedocument.Ilsuffit
davoirvucequestunprogrammeetcomprislesgrandsprincipesdelaprogrammation.
Celivreeststructurendeuxgrandesparties,traitantchacuneundesaspectsduC++.Lapremire
partie,contenantleschapitres112,traitedulangageC++luimme,desasyntaxeetdesesprinci
palesfonctionnalits.LadeuximepartiequantelleseconcentresurlabibliothquestandardC++,
quifournitunensembledefonctionnalitscohrentesetrutilisablespartouslesprogrammeurs.La
bibliothquestandardC++agalementlavantagedutiliserlesconstructionslesplusavancesdu
langage,etillustredoncparfaitementlesnotionsquiauronttabordesdanslapremirepartie.La
descriptiondelabibliothquestandardstendduchapitre13auchapitre18.
SilabibliothquestandardC++estdcriteendtail,ilnenvapasdemmepourlesfonctionsde
labibliothqueC. Vousnetrouverezdoncpasdanscelivreladescriptiondesfonctionsclassiques
duC, ni celledesfonctionslespluscourantesdelanormePOSIX.
Eneffet, bienqueprsentes
surquasimenttouslessystmesdexploitation,cesfonctionssontspcifiqueslanormePOSIXet
nappartiennentpasaulangageensoi.SeuleslesfonctionsincontournablesdelabibliothqueCseront
doncprsentesici. Si vousdsirezplusderenseignements, reportezvousauxspcificationsdes
appelssystmesPOSIXdelOpenGroup(http://www.unixsystems.org/single_unix_specification/),
ouladocumentationdesenvironnementsdedveloppementetlaidedeskitsdedveloppement
dessystmesdexploitation(SDK).
Celivreapour but deprsenter lelangageC++tel quil est dcrit par lanormeISO14882
dulangageC++. Cependant, bienquecettenormeait
tpublieen1999, letexteofficiel
nest paslibrement disponible. Commejeneveuxpascautionner lefait quuntextedenorme
international nesoit pas accessibletous, jemesuis rabattusur ledocument duprojet de
normalisationdulangage, datant du2dcembre1996et
intitulWorkingPaper
for Draft
Proposed International Standard for Information Systems Programming Language C++
(http://casteyde.christian.free.fr/cpp/cours/drafts/index.html).
Notezquelescompilateursquirespectentcettenormesecomptentencoresurlesdoigtsdunemain,
etquelesinformationsetexemplesdonnsicipeuventnepassavrerexactsaveccertainsproduits.
Enparticulier,certainsexemplesnecompilerontpasaveclescompilateurslesplusmauvais.Notez
galementquecertainesconstructionsdulangagenontpaslammesignificationavectouslescom
pilateurs,parcequellesonttimplmentesavantquelanormenelesspcifiecompltement.Ces
diffrencespeuventconduireducodenonportable,etonttsignaleschaquefoisdansunenote.
Lefaitquelesexemplesdecelivrenefonctionnentpasavecdetelscompilateursnepeutdoncpas
treconsidrcommeuneerreur,maispluttcommeunenonconformitdesoutilsutiliss,quisera
sansdoutelevedanslesversionsultrieuresdecesproduits.
Aprsavoirtentdefaireuneprsentationrigoureusedusujet,jaidciddarrangerleplandece
livredansunordrepluspdagogique.Ilestmonavisimpossibledeparlerdunsujetuntantsoit
peuvastedansunordrepurementmathmatique,cestdireunordreolesnotionssontintroduites
uneune,partirdesnotionsdjconnues(chaquefonction,oprateur,etc.napparatpasavantsa
dfinition). Untelplanncessiteraitdecouperletexteenmorceauxquinesontplusthmatiques.
Jai doncprisladcisiondeprsenterleschosesparordrelogique, et nonparordredencessit
syntaxique.
Lesconsquencesdecechoixsontlessuivantes:

ilfautadmettrecertaineschoses,quittelescomprendreplustard;

Avantpropos

ilfautliredeuxfoiscelivre.Lorsdelapremirelecture,onvoitlessentiel,etlorsdeladeuxime
lecture,oncomprendlesdtails(detoutesmanires,jefliciteceluiquicomprendtouteslessubti
litsduC++dupremiercoup).

Enfin, ce livre est undocument vivant. Il est librement tlchargeable sur mon site web
(http://casteyde.christian.free.fr),oladernireversionpeuttrercupre.Touteremarqueestdonc
labienvenue.Jetcheraidecorrigerleserreursquelonmesignaleradanslamesuredupossible,et
dapporterlesmodificationsncessairessiunpointestobscur.Sivousprenezletempsdemenvoyer
lesremarquesetleserreursquevousavezpudtecter,
jevoussauraisgrdevrifieraupralable
quellessonttoujoursdactualitdansladernireversiondecedocument.cettefin,unhistorique
desrvisionsatinclusenpremirepagepourpermettrelidentificationdesdiffrentesditionsde
cedocument.

ii

I.LelangageC++

LeC++estlundeslangagesdeprogrammationlesplusutilissactuellement.Ilestlafoisfacile
utiliseret trsefficace. Il souffrecependant delarputationdtrecompliquet illisible. Cette
rputationestenpartiejustifie.Lacomplexitdulangageestinvitablelorsquonchercheavoir
beaucoupdefonctionnalits.Enrevanche,encequiconcernelalisibilitdesprogrammes,toutdpend
delabonnevolontduprogrammeur.
LescaractristiquesduC++enfontunlangageidalpourcertainstypesdeprojets.Ilestincontour
nabledanslaralisationdesgrandsprogrammes.Lesoptimisationsdescompilateursactuelsenfont
galementunlangagedeprdilectionpourceuxquirecherchentlesperformances.Enfin,celangage
est,avecleC,idalpourceuxquidoiventassurerlaportabilitdeleursprogrammesauniveaudes
fichierssources(pasdesexcutables).
LesprincipauxavantagesduC++sontlessuivants:

grandnombredefonctionnalits;

performancesduC;

facilitdutilisationdeslangagesobjets;

portabilitdesfichierssources;

facilitdeconversiondesprogrammesCenC++,et,enparticulier,possibilitdutilisertoutesles
fonctionnalitsdulangageC;

contrlederreursaccru.

Ondisposedoncdequasimenttout:puissance, fonctionnalit, portabilitetsret. Larichessedu


contrlederreursdulangage, bassuruntypagetrsfort,
permet designalerungrandnombre
derreurslacompilation. Toutesceserreurssontautantderreursqueleprogrammenefaitpas
lexcution.LeC++peutdonctreconsidrcommeunsuperC.Lereversdelamdailleestque
lesprogrammesCnesecompilentpasdirectementenC++:ilestcourantquedesimplesavertisse
mentsenCsoientdeserreursblocantesenC++.Quelquesadaptationssontdoncsouventncessaires,
cependant,cellescisontminimes,puisquelasyntaxeduC++estbasesurcelleduC.Onremarquera
quetouslesprogrammesCpeuventtrecorrigspourcompilerlafoisenCetenC++.
Toutledbutdecettepartie(chapitres18)traitedesfonctionnalitscommunesauCetauC++,
eninsistantbiensurlesdiffrencesentrecesdeuxlangages.Ceschapitresprsententessentiellement
lasyntaxedesconstructionsdebaseduCetduC++.Ledbutdecettepartiepeutdoncgalement
treconsidrcommeuncoursallgsurlelangageC. Cependant, lesconstructionssyntaxiques
utilisessontcritesdetellesortequellessontcompilablesenC++.Celasignifiequellesnutilisent
pascertainesfonctionnalitsdouteusesduC.Ceuxquidsirentutiliserlapremirepartiecommeun
coursdeCdoiventdoncsavoirquilsagitduneversionpuredecelangage.
Enparticulier, les
appelsdefonctionsnondclaresoulesappelsdefonctionsavectropdeparamtresnesont
pas
considrscommedespratiquesdeprogrammationvalables.
Leschapitressuivants(chapitres812)netraitentqueduC++.LeChapitre8traitedelaprogramma
tionorienteobjetetdetouteslesextensionsquionttapportesaulangageCpourgrerlesobjets.
LeChapitre9prsentelemcanismedesexceptionsdulangage,quipermetdegrerleserreursplus
facilement.LidentificationdynamiquedestypesseradcritedansleChapitre10.LeChapitre11pr
sentelanotiondespacedenommage,quelonutiliseafindviterlesconflitsdenomsentrelesdiff
rentespartiesdungrandprojet.Enfin,leChapitre12dcritlemcanismedes template,quipermet
dcriredesportionsdecodeparamtrespardestypesdedonnesoupardesvaleursconstantes.

CesderniresnotionssontutilisesintensivementdanslabibliothquestandardC++,aussilalecture
compltedelapremirepartieestelleindispensableavantdesattaquerladeuxime.
Danstoutecettepremirepartie,lasyntaxeseradonne,saufexception,aveclaconventionsuivante:
cequiestentrecrochets( [et ])estfacultatif.Deplus,quandplusieurslmentsdesyntaxesont
sparsparunebarreverticale( |), lundeceslments, etunseulement, doittreprsent(cest
unouexclusif). Enfin, lespointsdesuspensiondsigneront uneitrationventuelledumotif
prcdent.
Parexemple,silasyntaxedunecommandeestlasuivante:
[fac|rty|sss]zer[(kfl[,kfl[...]])];

lescombinaisonssuivantesserontsyntaxiquementcorrectes:
zer;
faczer;
rtyzer;
zer(kfl);
ssszer(kfl,kfl,kfl,kfl);

maislacombinaisonsuivanteseraincorrecte:
facssszer()

pourlesraisonssuivantes:

facetssssontmutuellementexclusifs,bienquefacultatifstouslesdeux;

aumoinsunkflestncessairesilesparenthsessontmises;

ilmanquelepointvirgulefinal.

Rassurezvous, il nyaurapratiquement jamaisdesyntaxeaussi complique. Jesuissincrement


dsoldelacomplexitdecetexemple.

Chapitre1.PremireapprocheduC/C++
LeC/C++estunlangageprocdural,dummetypequelePascalparexemple.Celasignifiequeles
instructionssontexcuteslinairementetregroupesenblocs:lesfonctionsetlesprocdures(les
procduresnexistentpasenC/C++,cesontdesfonctionsquineretournentpasdevaleur).
Toutprogrammeapourbutdeffectuerdesoprationssurdesdonnes.Lastructurefondamentaleest
donclasuivante:
ENTREDESDONNES
(clavier,souris,fichier,autrespriphriques)
|
TRAITEMENTDESDONNES
|
SORTIEDESDONNES
(cran,imprimante,fichier,autrespriphriques)

Cesdiversestapespeuventtredispersesdansleprogramme.Parexemple,lesentrespeuventse
trouverdansleprogrammemme(lutilisateurnadanscecaspasbesoindelessaisir).Pourlaplupart
desprogrammes,lesdonnesenentreproviennentdufluxdentrestandard,etlesdonnesmises
ensortiesontdirigesverslefluxdesortiestandard.Toutefois,leprocessusdentredesdonnespeut
trerptautantdefoisquencessairependantlexcutiondunprogramme,etlesdonnestraites
aufuretmesurequellesapparaissent.Parexemple,pourlesprogrammesgraphiques,lesdonnes
sontreuesdelapartdusystmesousformedemessagescaractrisantlesvnementsgnrspar
lutilisateurouparlesystmeluimme(dplacementdesouris,fermeturedunefentre,appuisur
unetouche, etc.). Letraitementdesprogrammesgraphiquesestdoncuneboucleinfinie(quelon
appellelaboucledesmessages),quipermetdercuprerlesmessagesetdeprendrelesactionsen
consquence. Danscecas, lasortiedesdonnescorrespondaucomportement queleprogramme
adopteenrponsecesmessages.Celapeuttretoutsimplementdafficherlesdonnessaisies,ou,
plusgnralement,dappliquerunecommandeauxdonnesencoursdemanipulation.
Lesdonnesmanipulessont stockesdansdesvariables, cestdiredeszonesdelammoire.
Commeleurnomlindique,lesvariablespeuventtremodifies(parletraitementdesdonnes).Des
oprationspeuventdonctreeffectuessurlesvariables,maispasnimportelesquelles.Parexemple,
onnepeutpasajouterdespommesdesbananes,saufdfinircetteoprationbienprcisment.Les
oprationsdpendentdoncdelanaturedesvariables.
Afinderduirelesrisquesderreursdepro
grammation,leslangagescommeleC/C++donnentuntypechaquevariable(parexemple:pomme
etbanane).Lorsdelacompilation(phasedetraductiondutextesourceduprogrammeenexcutable),
cestypessontutilisspourvrifiersilesoprationseffectuessontautorises.Leprogrammeurpeut
videmmentdfinirsesproprestypes.
Lelangagefournitdestypesdebaseetdesoprationsprdfiniessurcestypes.Lesoprationsqui
peuvent trefaitessont soit lapplicationdunoprateur, soit lapplicationdunefonctionsurles
variables.Logiquementparlant,ilnyapasdediffrence.Seulelasyntaxechange:
a=2+3

estdoncstrictementquivalent:
a=ajoute(2,3)

Chapitre1.PremireapprocheduC/C++
videmment, desfonctionsutilisateur peuvent tredfinies. Lesoprateursnepeuvent treque
surchargs:ilestimpossibledendfinirdenouveaux(deplus,
lasurchargedesoprateursnest
faisablequenC++). Lanotiondesurchargedefonctionseradcriteendtailcidessous, dansla
Section1.6.4.
Cettepremirepartieest doncconsacreladfinitiondestypes, ladclarationdesvariables, la
constructionetlappeldefonctions,etauxentres/sortiesdebase(fluxdentre/sortiestandards).

1.1.LescommentairesenC++
Lescommentairessontncessairesettrssimplesfaire.Toutprogrammedoittrecomment.At
tentioncependant,tropdecommentairestuelecommentaire,parcequeleschosesimportantessont
noyesdanslesbanalits.
IlexistedeuxtypesdecommentairesenC++:lescommentairesdetypeCetlescommentairesdefin
deligne(quinesontdisponiblesquenC++).
LescommentairesCcommencentaveclasquencebarreobliquetoile.Lescommentairesseter
minentaveclasquenceinverse:unetoilesuiviedunebarreoblique.
Exemple11.CommentaireC
/*

CeciestuncommentaireC

*/

Cescommentairespeuventstendresurplusieurslignes.
Enrevanche,lescommentairesdefindelignessarrtentlafindelalignecourante,etpasavant.
Ilspermettent decommenterplusfacilement lesactionseffectuessurlalignecourante, avant le
commentaire. Lescommentairesdefindelignecommencent parlasquenceconstituededeux
barresobliques(ilsnontpasdesquencedeterminaison,puisquilsneseterminentqulafindela
lignecourante).Parexemple:
Exemple12.CommentaireC++
actionquelconque
actionsuivante

//CeciestuncommentaireC++

1.2.LestypesprdfinisduC/C++
LeC,etencoreplusleC++,estunlangagetyp.Celasignifiequechaqueentitmanipuledansles
programmesdoitdisposerduntypededonnegrceauquellecompilateurpourravrifierlavalidit
desoprationsquonluiappliquera.Lapriseencomptedutypedesdonnespeutapparatrecomme
unecontraintepourleprogrammeur, maisenralitilsagitsurtoutduneaideladtectiondes
erreurs.
Ilexisteplusieurstypesprdfinis.Cesont:

letypevide:void.Cetypeestutilispourspcifierlefaitquilnyapasdetype.Celaauneutilit
pourfairedesprocdures(fonctionsnerenvoyantrien)etlespointeurssurdesdonnesnontypes
(voirplusloin);

lesboolens: bool, qui peuvent prendrelesvaleurs true et false (enC++uniquement, ils


nexistentpasenC);

Chapitre1.PremireapprocheduC/C++

lescaractres:char;

lescaractreslongs:wchar_t(cenestuntypedebasequepourlelangageC++,maisilestgale
mentdfinidanslabibliothquestandardCetestdoncutilisablemalgrtoutenC);

lesentiers:int;

lesrels:float;

lesrelsendoubleprcision:double;

[et ]).Pourles
lestableauxunedimension,dontlesindicessontspcifispardescrochets(
tableauxdedimensionsuprieureougale2,onutiliseradestableauxdetableaux;

lesstructures,unionsetnumrations(voirplusloin).

Lestypesentiers(int)peuvent trecaractrissdundesmotsclslongoushort.
Cesmotscls
permettentdemodifierlatailledutype, cestdirelaplagedevaleursquilspeuventcouvrir. De
mme, lesrelsendoubleprcisionpeuvent trequalifisdumot cllong, cequi augmenteleur
plagedevaleurs.Onnepeutpasutiliserlemotclshortaveclesdouble.Ondisposedoncdetypes
additionnels:

lesentierslongs:longint,oulong(intestfacultatif);

lesentierscourts:shortint,oushort;

lesrelsenquadrupleprcision:longdouble.

Note:Attention!Ilnyapasdetypedebasepermettantdemanipulerleschanesdecaractres.
EnC/C++,leschanesdecaractressontenralitdestableauxdecaractres.Voustrouverez
plusloinpourdeplusamplesinformationssurleschanesdecaractresetlestableaux.

Latailledestypesnestspcifiedansaucunenorme.Laseulechosequiestindiquedanslanorme
C++,cestquelepluspetittypeestletypechar.Lestaillesdesautrestypessontdoncdesmultiples
decelledutypechar.Deplus,lesingalitssuivantessonttoujoursvrifies:
char shortint int longint
float double longdouble

oloprateur signifieici auneplagedevaleurpluspetiteougaleque.


Celadit, les
taillesdestypessontgnralementlesmmespourtouslesenvironnementsdedveloppement.Le
typecharest gnralement codsurunoctet (8bits), letypeshort int surdeuxoctetset letype
longintsurquatreoctets. Letypeintestceluiquipermetdestockerlesentiersauformatnatifdu
processeurutilis.Ilestdonccodsurdeuxoctetssurlesmachines16bitsetsurquatreoctetssur
lesmachines32bits.Enfin,latailledescaractresdetypewchar_tnestpasspcifieetdpendde
lenvironnementdedveloppementutilis.Ilssontgnralementcodssurdeuxousurquatreoctets
suivantlareprsentationutilisepourlescaractreslarges.
Note:Remarquezque,daprscequi prcde,letypeintdevraittrecodsur64bitssurles
machines64bits.Letypelongintdevantluitresuprieur,ildoitgalementtrecodsur64bits
ouplus.Letypeshortintpeutalorstresur16ousur32bits.Ilnexistedoncpas,selonlanorme,
detypepermettantdemanipulerlesvaleurs16bitssurlesmachines64bitssi letypeshortint
estcodsur32bits,ou,inversement,detypepermettantdemanipulerlesvaleurs32bitssi le
typeshortintestcodsur16bits.

Chapitre1.PremireapprocheduC/C++
Afindersoudrecesproblmes, laplupart descompilateursbrisent largleselonlaquellele
typeint est letypedesentiersnatifsduprocesseur, et fixent sataille32bitsquellequesoit
larchitectureutilise.Ainsi,letypeshortesttoujourscodsur16bits,letypeintsur32bitsetle
typelongsur32ou64bitsselonquelarchitecturedelamachineest32ou64bits.Autrement
dit,letypequi reprsentelesentiersnativementnestplusletypeint,maisletypelong.Celane
changepaslesprogrammes32bits,puisquecesdeuxtypessontidentiquesdanscecas.Les
programmesdestinsauxmachines64bitspourront quant euxtreoptimissenutilisant le
typelongchaquefoisquelonvoudrautiliserletypededonnesnatifdelamachinecible.Les
programmes16bitsenrevanchentnesontenrevanchepluscompatiblesaveccesrgles,mais
laplupartdescompilateursactuelsnepermettentplusdecompilerdesprogrammes16bitsde
toutesmanires.

Lestypeschar,wchar_tetintpeuventtresignsounon.Unnombresignpeuttrengatif,pasun
nombrenonsign.Lorsquunnombreestsign,lavaleurabsolueduplusgrandnombrereprsentable
estpluspetite.Pardfaut,lesnombresentierssontsigns.Lesignedestypescharetwchar_tdpend
ducompilateurutilis,ilestdoncprfrabledespcifiersystmatiquementsicestypessontsignsou
nonlorsquonlesutiliseentantquetypeentier.Pourprciserquunnombrenestpassign,ilfaut
utiliserlemotclunsigned.Pourprciserquunnombreestsign,onpeututiliserlemotclsigned.
Cesmotsclspeuventtreintervertislibrementaveclesmotsclslongetshortpourlestypesentiers.
Exemple13.Typessignsetnonsigns
unsignedchar
signedchar
unsignedwchar_t
signedwchar_t
unsignedint
signedint
unsignedlongint
longunsignedint
Note:LeC++(etleC++uniquement)considrelestypescharetwchar_tcommelestypesde
basedescaractres.LelangageC++distinguedonclesversionssignesetnonsignesdeces
typesdelaversiondontlesignenestpasspcifi,puisquelescaractresnontpasdenotion
designeassocie.CelasignifiequelescompilateursC++traitentlestypeschar,unsignedchar
etsignedcharcommedestypesdiffrents,etilenestdemmepourlestypeswchar_t,signed
wchar_tetunsignedwchar_t.Cettedistinctionnapaslieudtreauniveaudesplagesdevaleurs
silonconnatlesignedutypeutiliseninternepourreprsenterlestypescharetwchar_t,mais
elleest trsimportantedansladterminationdela signaturedesfonctions, enparticulierau
niveaudumcanismedesurchargedesfonctions.Lesnotionsdesignatureetdesurchargedes
fonctionsserontdtaillesplusloindanscecours.

Lesvaleursaccessiblesaveclesnombressignsnesontpaslesmmesquecellesaccessiblesavecles
nombresnonsigns.Eneffet,unbitestutilispourlesignedanslesnombressigns.Parexemple,si
letypecharestcodsur8bits,onpeutcoderlesnombresallantde0255aveccetypeennonsign
(ilya8chiffresbinaires,chacunpeutvaloir0ou1,onadonc2puissance8combinaisonspossibles,
cequifait256).Ensign,lesvaleursstendentde128127(undeschiffresbinairesestutilispour
lesigne,ilenreste7pourcoderlenombre,doncilreste128possibilitsdanslespositifscommedans
lesngatifs.0estconsidrcommepositif.Entout,ilyaautantdepossibilits.).
Demme,siletypeintestcodsur16bits(casdesmachines16bits),lesvaleursaccessiblesvont
de3276832767oude065535silentiernestpassign.CestlecassurlesPCenmoderel

Chapitre1.PremireapprocheduC/C++
(cestdiresousDOS)etsousWindows3.x.Surlesmachinesfonctionnanten32bits,letypeintest
stocksur32bits:lespacedesvaleursdisponiblesestdonc65536foispluslarge.Cestlecassur
lesPCenmodeprotg32bits(Windows9xouNT,DOSExtender,Linux)etsurlesMacintosh.Sur
lesmachines64bits,letypeintdevraittre64bits(DECAlphaetlaplupartdesmachinesUNIXpar
exemple).
Enfin,letypefloatestgnralementcodsur4octets,etlestypesdoubleetlongdoublesontsouvent
identiquesetcodssur8octets.
Note:Onconstatedoncquelaportabilitdestypesdebaseesttrsalatoire.Celasignifiequil
fautfaireextrmementattentiondanslechoixdestypessilonveutfaireducodeportable(cest
direqui compileraetfonctionnerasansmodificationduprogrammesurtouslesordinateurs).Il
estdanscecasncessairedutiliserdestypesdedonnesquidonnentlesmmesintervallesde
valeurssurtouslesordinateurs.LanormeISOC99imposededfinirdestypesportablesafinde
rglercesproblmessurtouteslesarchitecturesexistantes.Cestypessontdfinisdanslefichier
dentte stdint.h .Il sagitdestypesint8_t,int16_t,int32_tetint64_t,etdeleursversionsnon
signesuint8_t,uint16_t,uint32_tetuint64_t.Latailledecestypesenbitsestindiquedansleur
nometleurutilisationnedevraitpasposerdeproblme.
Delammemanire,deuxreprsentationsdunmmetypepeuventtrediffrentesenmmoire
surdeuxmachinesdarchitecturesdiffrentes,mmetaillegaleennombredebits.Leprob
lmelepluscourantestlordredestockagedesoctetsenmmoirepourlestypesquisontstocks
surplusdunoctet(cestdirequasimenttous).Celaauneimportancecapitalelorsquedesdon
nesdoiventtrechangesentredesmachinesdarchitecturesaprioridiffrentes,parexemple
danslecadredunecommunicationrseau,oulorsdeladfinitiondesformatsdefichiers.Une
solutionsimpleestdetoujoursdchangerlesdonnesauformattexte,oudechoisirunmode
dereprsentationderfrence. Lesbibliothquesrseaudisposent gnralement desmth
odespermettantdeconvertirlesdonnesversunformatcommundchangededonnesparun
rseauetpourrontparexempletreutilises.

1.3.Notationdesvaleurs
Lesentierssenotentdelamaniresuivante:

base10(dcimale):avecleschiffresde09,etlessignes+(facultatif)et.
Exemple14.Notationdesentiersenbase10
12354,2564

base16(hexadcimale): avecleschiffres09et AFouaf(A=a=10, B=b=11, ...


F=f=15).Lesentiersnotsenhexadcimaldevronttoujourstreprcdsde0x(quiindiquela
base).Onnepeutpasutiliserlesigneaveclesnombreshexadcimaux.
Exemple15.Notationdesentiersenbase16
0x1AE

Chapitre1.PremireapprocheduC/C++

base8(octale):avecleschiffresde07.Lesnombresoctauxdoiventtreprcdsdun0(qui
indiquelabase).Lesignenepeutpastreutilis.
Exemple16.Notationdesentiersenbase8
01,0154

Lesflottants(pseudorels)senotentdelamaniresuivante:
[signe]chiffres[.[chiffres]][e|E[signe]exposant][f]

o signe indiquelesigne.Onemploielessignes+(facultatif)etaussibienpourlamantisseque
pourlexposant. eou Epermetdedonnerlexposantdunombreflottant.Lexposantestfacultatif.
Sionnedonnepasdexposant, ondoitdonnerdeschiffresderrirelavirguleavecunpointetces
chiffres.Lesuffixe fpermetdeprcisersilenombreestdetypefloatounon(auquelcasilsagit
dundouble).
Leschiffresaprslavirgulesontfacultatifs,maispaslepoint.Sionnemetnilepoint,nilamantisse,
lenombreestunentierdcimal.
Exemple17.Notationdesrels
123.56f,12e12,2

2estentier,2.festrel.
Lescaractressenotententreguillemetssimples:
A,c,(

Onpeut donneruncaractrenonaccessibleauclavierendonnant soncodeenoctal, prcddu


caractre\.Parexemple,lecaractreApeutaussitrenot\101.Remarquezquecettenotation
estsemblablelanotationdesnombresentiersenoctal,etquele0initialestsimplementremplac
parun\. Il est aussi possibledenoterlescaractresavecleurcodeenhexadcimal,
laidede
lanotation \xNN , o NN est lecodehexadcimal ducaractre. Enfin, il existedessquences
dchappement particuliresqui permettent decodercertainscaractresspciauxplusfacilement.
Lesprincipalessquencesdchappementsontlessuivantes:
\a
\b
\f
\r
\n
\t
\v

Bipsonore
Backspace
Dbutdepagesuivante
Retourlaligne(sanssautdeligne)
Passagelaligne
Tabulation
Tabulationverticale

Dautressquencesdchappementsontdisponibles,afindepouvoirreprsenterlescaractresayant
unesignificationparticulireenC:
\\
\"

Lecaractre\
Lecaractre"

Chapitre1.PremireapprocheduC/C++
\

Lecaractre

Bienquil nexistepasproprement parlerdechanesdecaractresenC/C++, il est possiblede


dfinirdestableauxdecaractresconstantsutilisablesentantquechanesdecaractresendonnant
leurcontenuentredoublesguillemets:
"Exempledechanedecaractres..."

Lescaractresspciauxpeuventtreutilissdirectementdansleschanesdecaractresconstantes:
"Ceciestunsautdeligne:\nCeciestlalignesuivante."

Siunechanedecaractresconstanteesttroplonguepourtenirsuruneseuleligne,onpeutconcatner
plusieurschanesenlesjuxtaposant:
"Ceciestlapremirechane"

"ceciestladeuxime."

produitlachanedecaractrescompltesuivante:
"Ceciestlapremirechanececiestladeuxime."

Note: Attention: il nefaut pasmettredecaractrenul dansunechanedecaractres. Ce


caractreesteneffetlecaractredeterminaisondetoutechanedecaractres.

Enfin,lesversionslonguesdesdiffrentstypescitsprcdemment(wchar_t,longintetlongdouble)
peuventtrenotesenfaisantprcderousuivrelavaleurdelalettreL.Cettelettredoitprcderla
valeurdanslecasdescaractresetdeschanesdecaractresetlasuivrequandilsagitdesentierset
desflottants.Parexemple:
L"Ceciestunechanedewchar_t."
2.3e5L

1.4.Ladfinitiondesvariables
Lesvariablessimplespeuventtredfiniesaveclasyntaxesuivante:
typeidentificateur;
identificateur est sonnom. Il est possibledecreret
otypeest letypedelavariableet
dinitialiserunesriedevariablesdsleurcrationaveclasyntaxesuivante:
typeidentificateur[=valeur][,identificateur[=valeur][...]];

Chapitre1.PremireapprocheduC/C++
Exemple18.Dfinitiondevariables
inti=0,j=0;
doublesomme;

/*Dfinitetinitialisedeuxentiers0*/
/*Dclareunevariablerelle*/

Lesvariablespeuventtredfiniesquasimentnimporteodansleprogramme.
dfinirunevariabletemporairequelolonenabesoin.

Celapermetdene

Note:Celanestvrai quenC++.EnCpur,onestobligdedfinirlesvariablesaudbutdes
fonctionsoudesinstructionscomposes(voirplusloin).Ilfautdoncconnatrelesvariablestem
porairesncessaireslcrituredumorceaudecodequisuitleurdfinition.

Ladfinitiondunevariablenesuffit pas, engnral, linitialiser. Lesvariablesnoninitialises


contenantdesvaleursalatoires,ilfautviterdelesutiliseravantuneinitialisationcorrecte.Initialiser
lesvariablesquelondclareleurvaleurpardfautestdoncunebonnehabitudeprendre.Celaest
dailleursobligatoirepourlesvariablesconstantesquelonpeutdclareraveclemotcl const,
carcesvariablesnepeuventpastremodifiesaprsleurdfinition.Cemotclseraprsentendtail
danslaSection3.2.
Note:Si lesvariablesutilisant lestypessimplesnesont pasinitialiseslorsdeleurdfinition
demaniregnrale, cenest paslecaspourlesobjetsdont letypeest uneclassedfinie
parlutilisateur.Eneffet,pourcesobjets,lecompilateurappelleautomatiquementunefonction
dinitialisationappeleleconstructeurlorsdeleurdfinition.Lamanirededfinirdesclasses
dobjetsainsi quetouteslesnotionstraitant delaprogrammationobjet seront dcritesdansle
Chapitre8.

Ladfinitionduntableausefaitenfaisantsuivrelenomdelidentificateurdunepairedecrochets,
contenantlenombredlmentdutableau:
typeidentificateur[taille]([taille](...));

Note:Attention!Lescaractres[et ]tantutilissparlasyntaxedestableaux,ilsnesignifient
plusleslmentsfacultatifsici. Ici,et ici seulement,leslmentsfacultatifssont donnsentre
parenthses.

Danslasyntaxeprcdente,typereprsenteletypedeslmentsdutableau.
Exemple19.Dfinitionduntableau
intMonTableau[100];
MonTableau estuntableaude100entiers.Onrfrenceleslmentsdestableauxendonnantlindice

dellmententrecrochet:
MonTableau[3]=0;

Chapitre1.PremireapprocheduC/C++
Note:Lasyntaxepermettantdinitialiserlestableauxdsleurcrationestunpeupluscomplexe
quecellepermettantdinitialiserlesvariablesdetypesimple.Cettesyntaxeestsemblablecelle
permettantdinitialiserlesstructuresdedonnesetseradoncdcritedanslasectionquileurest
ddie.

EnC/C++,lestableauxplusdunedimensionsontdestableauxdetableaux.Onprendragardeau
faitquedansladfinitionduntableauplusieursdimensions,laderniretailleindiquespcifiela
tailledutableaudontonfaituntableau.Ainsi,danslexemplesuivant:
intMatrice[5][4];
Matrice estuntableaudetaille5dontleslmentssonteuxmmesdestableauxdetaille4.Lordre

dedclarationdesdimensionsestdoncinvers:5estlatailledeladerniredimensionet4estlataille
delapremiredimension.Llmentsuivant:
Matrice[2];

estdoncletroisimelmentdecetableaudetaillecinq,etestluimmeuntableaudequatrel
ments.
EnC/C++,lesindicesdestableauxvarientde 0 taille1.Ilyadoncbientaillelmentsdans
letableau.Danslexempledonncidessus,llment MonTableau[100] nexistepas:yaccder
planteraleprogramme.Cestauprogrammeurdevrifierquesesprogrammesnutilisentjamaisles
tableauxavecdesindicesplusgrandsqueleurtailleoungatifs.
Unautrepointauquelilfaudrafaireattentionestlatailledestableauxutiliserpourleschanesde
caractres.Unechanedecaractressetermineobligatoirementparlecaractrenul(\0),ilfautdonc
rserverdelaplacepourlui.Parexemple,pourcrerunechanedecaractresde100caractresau
plus,ilfautuntableaupour101caractres(dclaravec charchaine[101]; ).

1.5.Instructionsetoprations
Lesinstructionssontgnralementidentifiesparlepointvirgule.Cestcecaractrequimarquela
finduneinstruction.
Exemple110.Instructionvide
;

/*Instructionvide:nefaitrien!*/

Ilexisteplusieurstypesdinstructions,quipermettentderaliserdesoprationsvaries.Lesinstruc
tionslespluscourantessontsansdoutelesinstructionsquieffectuentdesoprations,cestdireles
instructionsquicontiennentdesexpressionsutilisantdesoprateurs.
LesprincipalesoprationsutilisablesenC/C++sontlessuivantes:

lesaffectations:
variable=valeur
Note:Lesaffectationsnesontpasdesinstructions.Cesontbiendes oprationsqui renvoient
la valeur affecte.Onpeutdonceffectuerdesaffectationsmultiples:

Chapitre1.PremireapprocheduC/C++
i=j=k=m=0;

/*Annulelesvariablesi,j,ketm.*/

lesoprationsdebasedulangage:
valeuropvaleur

o op estlundesoprateurssuivants: +, , *, /, %, &, |, ^, ~, <<, >>.


Note: / reprsenteladivisioneuclidiennepourlesentiersetladivisionclassiquepourles
flottants.

%reprsentelacongruence(cestdirelerestedeladivisioneuclidienne).|et &reprsentent
respectivementleouetleetbinaire(cestdirebitbit:1et1=1,0etx=0,1oux=1et0ou0
=0). ^reprsenteleouexclusif (1xor1=0,0xor0=0et1xor0=1). ~reprsentelangation
binaire(1devient0etviceversa). <<et >>effectuentundcalagebinaireverslagaucheetla
droiterespectivement,dunnombredebitsgallavaleurdusecondoprande.

lesoprationsdesautresoprateursdulangage.
LeCet leC++disposent doprateursunpeu
plusvolusquelesoprateurspermettantderaliserlesoprationsdebasedulangage.Cesop
rateurssont lesoprateursdincrmentationet dedcrmentation ++ et , loprateurternaire
dvaluationconditionnelleduneexpression(oprateur ?:)etloprateurvirgule(oprateur ,).
Lasyntaxedecesoprateursestdcritecidessous.

lesappelsdefonctions.
suivantes.

Nousverronscommentcrireetappelerdesfonctionsdanslessections

Bienentendu,laplupartdesinstructionscontiendrontdesaffectations.Cesontdoncsansdouteles
affectationsquisontlesplusutilisesparmilesdiversesoprationsralisables,aussileCetleC++
permettentilslutilisationdaffectationscomposes.Uneaffectationcomposeestuneoprationper
mettantderaliserenuneseuletapeuneoprationnormaleetlaffectationdesonrsultatdansla
variableservantdepremieroprande.Lesaffectationscomposesutilisentlasyntaxesuivante:
variableop_affvaleur

o op_aff estlundesoprateurssuivants:+=,=,*=,etc.Cettesyntaxeeststrictementqui
valente:
variable=variableopvaleur

etpermetdoncdemodifierlavaleurde variable enluiappliquantloprateur op.


Exemple111.Affectationcompose
i*=2;

/*Multiplieipar2:i=i*2.*/

Lesoprateursdincrmentationetdedcrmentation ++ et sappliquentcommedesprfixesou
dessuffixessurlesvariables.Lorsquilssontenprfixe,lavariableestincrmenteoudcrmente,

10

Chapitre1.PremireapprocheduC/C++
puissavaleurestrenvoye.Silssontensuffixe,lavaleurdelavariableestrenvoye,puislavariable
estincrmenteoudcrmente.Parexemple:
inti=2,j,k;
j=++i;
k=j++;

/*lafindecetteinstruction,ietjvalent3.*/
/*lafindecetteligne,kvaut3etjvaut4.*/

Note:Onprendragardenutiliserlesoprateursdincrmentationetdedcrmentationpost
fixsquelorsquecelaestrellementncessaire.Eneffet,cesoprateursdoiventcontruireun
objettemporairepourrenvoyerlavaleurdelavariableavantincrmentationoudcrmentation.
Si cetobjettemporairenestpasutilis,il estprfrabledutiliserlesversionsprfixesdeces
oprateurs.

Loprateurternairedvaluationconditionnelle?: estleseuloprateurquidemande3paramtres(
partloprateurfonctionnel () desfonctions,quiadmetnparamtres,etquelondcriraplustard).
Cetoprateurpermetderaliseruntestsuruneconditionetdecalculeruneexpressionouuneautre
selonlersultatdecetest.Lasyntaxedecetoprateurestlasuivante:
test?expression1:expression2

Danscettesyntaxe, test estvaluenpremier.Sonrsultatdoittreboolenouentier.Si test est


vrai(ousisavaleurestnonnulle), expression1 estcalculeetsavaleurestrenvoye.Sinon,cest
lavaleurde expression2 quiestrenvoye.Parexemple,lexpression:
Min=(i<j)?i:j;

calculeleminimumde i etde j.
Loprateurvirgule,quantlui,permetdvaluerplusieursexpressionssuccessivementetderenvoyer
lavaleurdeladernireexpression.Lasyntaxedecetoprateurestlasuivante:
expression1,expression2[,expression3[...]]

o expression1, expression2,etc.sontlesexpressionsvaluer.Lesexpressionssontvalues
degauchedroite,puisletypeetlavaleurdeladernireexpressionsontutilisspourrenvoyerle
rsultat.Parexemple,lissuedesdeuxlignessuivantes:
doubler=5;
inti=r*3,1;
r vaut5et i vaut1. r*3 estcalculpourrien.
Note:Cesdeuxderniersoprateurspeuventnuiregravementlalisibilitdesprogrammes.Ilest
toujourspossibledercrireleslignesutilisantloprateurternaireavecuntest(voirlaSection
2.1pourlasyntaxedestestsenC/C++).Demme,onpeuttoujoursdcomposeruneexpression
utilisantloprateurvirguleendeuxinstructionsdistinctes.Cedernieroprateurnedevradonc
jamaistreutilis.

11

Chapitre1.PremireapprocheduC/C++
Ilestpossibledecrerdesinstructionscomposes,constituesdinstructionsplussimples.Lesins
tructionscomposesseprsententsouslaformedeblocdinstructionsolesinstructionscontenues
sontencadresdaccoladesouvrantesetfermantes(caractres { et }).
Exemple112.Instructioncompose
{
i=1;
j=i+3*g;
}
Note:Unblocdinstructionsestconsidrcommeuneinstructionunique.Il estdoncinutilede
mettreunpointvirgulepourmarquerlinstruction,puisqueleblocluimmeestuneinstruction.

Enfin,ilexistetoutunjeudinstructionsquipermettentdemodifierlecoursdelexcutiondupro
gramme,commelestests,lesbouclesetlessauts.Cesinstructionsserontdcritesendtaildansle
chapitretraitantdesstructuresdecontrle.

1.6.Lesfonctions
LeC++nepermetdefairequedesfonctions,
pasdeprocdures. Uneprocdurepeuttrefaiteen
utilisantunefonctionnerenvoyantpasdevaleurouenignorantlavaleurretourne.

1.6.1.Dfinitiondesfonctions
Ladfinitiondesfonctionssefaitcommesuit:
typeidentificateur(paramtres)
{
...
/*Instructionsdelafonction.*/
}

typeestletypedelavaleurrenvoye, identificateur estlenomdelafonction,et paramtres


estunelistedeparamtres.Lasyntaxedelalistedeparamtresestlasuivante:
typevariable[=valeur][,typevariable[=valeur][...]]

otypeestletypeduparamtre variable quilesuitet valeur savaleurpardfaut.Lavaleurpar


dfautdunparamtreestlavaleurqueceparamtreprendsiaucunevaleurneluiestattribuelors
delappeldelafonction.
Note:LinitialisationdesparamtresdefonctionsnestpossiblequenC++,leCnacceptepas
cettesyntaxe.

Lavaleurdelafonctionrenvoyerestspcifieenutilisantlacommande return,dontlasyntaxe
est:
returnvaleur;

12

Chapitre1.PremireapprocheduC/C++

Exemple113.Dfinitiondefonction
intsomme(inti,intj)
{
returni+j;
}

Siunefonctionnerenvoiepasdevaleur,onluidonneraletypevoid.Siellenattendpasdeparamtres,
salistedeparamtresseravoidounexisterapas. Ilnestpasncessairedemettreuneinstruction
returnlafindunefonctionquinerenvoiepasdevaleur.
Exemple114.Dfinitiondeprocdure
voidrien()
{
return;
}

/*Fonctionnattendantpasdeparamtres*/
/*etnerenvoyantpasdevaleur.*/
/*Cetteligneestfacultative.*/

1.6.2.Appeldesfonctions
Lappeldunefonctionsefaitendonnantsonnom, puislesvaleursdesesparamtresentreparen
thses.Attention!Silnyapasdeparamtres,ilfautquandmmemettrelesparenthses,sinonla
fonctionnestpasappele.
Exemple115.Appeldefonction
inti=somme(2,3);
rien();

Siladclarationcomprenddesvaleurspardfautpourdesparamtres(C++seulement),cesvaleurs
sontutiliseslorsquecesparamtresnesontpasfournislorsdelappel.Siunparamtreestmanquant,
alorstouslesparamtresquilesuiventdoiventeuxaussitreomis.Ilenrsultequeseulslesderniers
paramtresdunefonctionpeuventavoirdesvaleurspardfaut.Parexemple:
inttest(inti=0,intj=2)
{
returni/j;
}

Lappel delafonction test(8) est valide. Commeonneprcisepasledernierparamtre, j est


initialis 2. Lersultatobtenuestdonc 4. Demme, lappel test() estvalide:danscecas i
vaut 0 et j vaut 2.Enrevanche,ilestimpossibledappelerlafonction test enneprcisantquela
valeurde j .Enfin,lexpression inttest(inti=0,intj){...} seraitinvalide,carsion
nepassaitpasdeuxparamtres, j neseraitpasinitialis.

13

Chapitre1.PremireapprocheduC/C++

1.6.3.Dclarationdesfonctions
Toutefonctiondoittredclareavantdtreappelepourlapremirefois.Ladfinitiondunefonc
tionpeutfaireofficededclaration.
Ilpeutsetrouverdessituationsounefonctiondoittreappeledansuneautrefonctiondfinieavant
elle.Commecettefonctionnestpasdfinieaumomentdelappel,elledoittredclare.Demme,
ilestcourantdavoirappelerunefonctiondfiniedansunautrefichierquelefichierdosefait
lappel.Encoreunefois,ilestncessairededclarercesfonctions.
Lerledesdclarationsestdoncdesignalerlexistencedesfonctionsauxcompilateursafindeles
utiliser,toutenreportantleurdfinitionplusloinoudansunautrefichier.
Lasyntaxedeladclarationdunefonctionestlasuivante:
typeidentificateur(paramtres);

otypeest

letypedelavaleur renvoyepar lafonction, identificateur est sonnomet


paramtres lalistedestypesdesparamtresquelafonctionadmet,
ventuellement avecleurs
valeurspardfaut,etsparspardesvirgules.
Exemple116.Dclarationdefonction
intMin(int,int);

/*Dclarationdelafonctionminimum*/
/*dfinieplusloin.*/

/*Fonctionprincipale.*/
intmain(void)
{
inti=Min(2,3);
/*AppellafonctionMin,dj
dclare.*/
return0;
}
/*Dfinitiondelafonctionmin.*/
intMin(inti,intj)
{
if(i<j)returni;
elsereturnj;
}

Silondonnedesvaleurspardfautdiffrentesauxparamtresdunefonctiondansplusieursdcla
rationsdiffrentes,lesvaleurspardfaututilisessontcellesdeladclarationvisiblelorsdelappel
delafonction.Siplusieursdclarationssontvisiblesetentrentenconflitauniveaudesvaleurspar
dfautdesparamtresdelafonction,lecompilateurnesaurapasquelledclarationutiliseretsigna
lerauneerreurlacompilation.Enfin,ilestpossibledecomplterlalistedesvaleurspardfautde
ladclarationdunefonctiondanssadfinition.Danscecas,lesvaleurspardfautspcifiesdansla
dfinitionnedoiventpasentrerenconflitaveccellesspcifiesdansladclarationvisibleaumoment
deladfinition,fautedequoilecompilateursignalerauneerreur.

1.6.4.Surchargedesfonctions
IlestinterditenCdedfinirplusieursfonctionsquiportentlemmenom.EnC++,cetteinterdiction
estleve,moyennantquelquesprcautions.Lecompilateurpeutdiffrencierdeuxfonctionsenregar
dantletypedesparamtresquellereoit.Lalistedecestypessappellelasignaturedelafonction.
Enrevanche,letypedursultatdelafonctionnepermetpasdelidentifier,carlersultatpeutnepas

14

Chapitre1.PremireapprocheduC/C++
treutilisoupeuttreconvertienunevaleurdunautretypeavantdtreutilisaprslappeldecette
fonction.
Il est doncpossibledefairedesfonctionsdemmenom(onlesappellealorsdessurcharges)si
et seulement si touteslesfonctionsportant cenompeuvent tredistinguesparleurssignatures.
Lasurchargequiseraappeleseracelledontlasignatureestlaplusprochedesvaleurspassesen
paramtrelorsdelappel.
Exemple117.Surchargedefonctions
floattest(inti,intj)
{
return(float)i+j;
}
floattest(floati,floatj)
{
returni*j;
}

Cesdeuxfonctionsportentlemmenom, etlecompilateurlesaccepteratouteslesdeux.
Lorsde
lappelde test(2,3),ceseralapremirequiseraappele,car2 et 3 sontdesentiers.Lorsdelappel
de test(2.5,3.2),ceseraladeuxime,parceque 2.5 et 3.2 sontrels.Attention!Dansunappel
telque test(2.5,3),leflottant 2.5 seraconvertienentieretlapremirefonctionseraappele.Il
convientdoncdefairetrsattentionauxmcanismesdesurchargedulangage,etdevrifierlesrgles
deprioritutilisesparlecompilateur.
Onveilleranepasutiliserdesfonctionssurchargesdontlesparamtresontdesvaleurspardfaut,
carlecompilateurnepourraitpasfaireladistinctionentrecesfonctions.Dunemaniregnrale,le
compilateurdisposedunensembledergles(dontlaprsentationdpasselecadredecelivre)qui
luipermettentdedterminerlameilleurefonctionappelertantdonnunjeudeparamtres.Si,lors
delarecherchedelafonctionutiliser,lecompilateurtrouvedesambiguts,ilgnreuneerreur.

1.6.5.Fonctionsinline
LeC++disposedumotcl inline,quipermetdemodifierlamthodedimplmentationdesfonc
tions.Placdevantladclarationdunefonction,ilproposeaucompilateurdenepasinstanciercette
fonction.Celasignifiequelondsirequelecompilateurremplacelappeldelafonctionparlecode
correspondant.Silafonctionestgrosseousielleestappelesouvent,leprogrammedevientplusgros,
puisquelafonctionestrcritechaquefoisquelleestappele.Enrevanche,ildevientnettement
plusrapide,puisquelesmcanismesdappeldefonctions,depassagedesparamtresetdelavaleurde
retoursontainsivits.Deplus,lecompilateurpeuteffectuerdesoptimisationsadditionnellesquil
nauraitpaspufairesilafonctionntaitpasinline.Enpratique,onrserveracettetechniquepour
lespetitesfonctionsappelesdansducodedevanttrerapide(lintrieurdesbouclesparexemple),
oupourlesfonctionspermettantdeliredesvaleursdansdesvariables.
Cependant,ilfautsemfier.Lemotcl inline estunindiceindiquantaucompilateurdefairedes
fonctions inline.Ilnyestpasoblig.Lafonctionpeutdonctrsbientreimplmenteclassique
ment. Pire, ellepeuttreimplmentedesdeuxmanires, selonlesmcanismesdoptimisationdu
compilateur.Demme,lecompilateurpeutgalementinlinerlesfonctionsnormalesafindoptimiser
lesperformancesduprogramme.
Deplus,ilfautconnatrelesrestrictionsdesfonctions inline :

15

Chapitre1.PremireapprocheduC/C++

ellesnepeuventpastrercursives;

ellesnesontpasinstancies,donconnepeutpasfairedepointeursurunefonction

inline.

Silunedecesdeuxconditionsnestpasvrifiepourunefonction,lecompilateurlimplmentera
classiquement(elleneseradoncpas inline).
Enfin,dufaitquelesfonctionsinline sontinsrestellesquellesauxendroitsoellessontappeles,
ilestncessairequellessoientcompltementdfiniesavantleurappel.Celasignifieque,contraire
mentauxfonctionsclassiques,ilnestpaspossibledesecontenterdelesdclarerpourlesappeler,
etdefournirleurdfinitiondansunfichierspar. Danscecaseneffet, lecompilateurgnrerait
desrfrencesexternessurcesfonctions,etninsreraitpasleurcode.Cesrfrencesneseraientpas
rsolueslditiondelien, carilnegnregalementpaslesfonctions inline,puisquellessont
supposestreinsressurplacelorsquonlesutilise.Lesnotionsdecompilationdansdesfichiers
sparsetdditiondeliensserontprsentesendtaildansleChapitre6.
Exemple118.Fonctioninline
inlineintMax(inti,intj)
{
if(i>j)
returni;
else
returnj;
}

Pourcetypedefonction,ilesttoutfaitjustifidutiliserlemotcl inline.

1.6.6.Fonctionsstatiques
Pardfaut,lorsquunefonctionestdfiniedansunfichierC/C++,ellepeuttreutilisedanstoutautre
fichierpourvuquellesoitdclareavantsonutilisation.Danscecas,lafonctionestditeexterne.Il
peutcependanttreintressantdedfinirdesfonctionslocalesunfichier,soitafindersoudredes
conflitsdenoms(entredeuxfonctionsdemmenometdemmesignaturemaisdansdeuxfichiers
diffrents),soitparcequelafonctionestuniquementdintrtlocal.LeCetleC++fournissentdonc
lemotcl static qui,unefoisplacdevantladfinitionetlesventuellesdclarationsdunefonc
tion,larenduniqueetutilisableuniquementdanscefichier.partcedtail,lesfonctionsstatiques
sutilisentexactementcommedesfonctionsclassiques.
Exemple119.Fonctionstatique
//Dclarationdefonctionstatique:
staticintlocale1(void);
/*Dfinitiondefonctionstatique:*/
staticintlocale2(inti,floatj)
{
returni*i+j;
}

Lestechniquespermettantdedcouperunprogrammeenplusieursfichierssourcesetdegnrerles
fichiersbinairespartirdecesfichiersserontdcritesdanslechapitretraitantdelamodularitdes
programmes.

16

Chapitre1.PremireapprocheduC/C++

1.6.7.Fonctionsprenantunnombrevariabledeparamtres
Engnral,lesfonctionsontunnombreconstantdeparamtres.Pourlesfonctionsquiontdespara
mtrespardfautenC++,lenombredeparamtrespeutapparatrevariablelappeldelafonction,
maisenralit,lafonctionutilisetoujourslemmenombredeparamtres.
LeCetleC++disposenttoutefoisdunmcanismequipermetauprogrammeurderaliserdesfonc
tionsdontlenombreetletypedesparamtressontvariables.Nousverronsplusloinquelesfonctions
dentre/sortieduCsontdesfonctionsdontlalistedesargumentsnestpasfixe,celaafindepouvoir
raliserunnombrearbitrairedentres/sorties,etcesurnimportequeltypeprdfini.
Engnral,lesfonctionsdontlalistedesparamtresestarbitrairementlonguedisposentduncritre
poursavoirquelestledernierparamtre.Cecritrepeuttrelenombredeparamtres,quipeuttre
fournienpremierparamtrelafonction,ouunevaleurdeparamtreparticulirequidterminelafin
delalisteparexemple.Onpeutaussidfinirlesparamtresquisuiventlepremierparamtrelaide
dunechanedecaractres.
Pourindiqueraucompilateurquunefonctionpeutaccepterunelistedeparamtresvariable,ilfaut
simplementutiliserdespointsdesuspensionsdanslalistedesparamtres:
typeidentificateur(paramtres,...)

danslesdclarationsetladfinitiondelafonction.Danstouslescas,ilestncessairequelafonction
aitaumoinsunparamtreclassique.Lesparamtresclassiquesdoiventimprativementtreavantles
pointsdesuspensions.
Ladifficultapparatenfaitdanslamaniredercuprerlesparamtresdelalistedeparamtresdans
ladfinitiondelafonction.Lesmcanismesdepassagedesparamtrestanttrsdpendantsdela
machine(etducompilateur),unjeudemacrosatdfinidanslefichierdentte stdarg.h pour
faciliterlaccsauxparamtresdelaliste.Pourensavoirplussurlesmacrosetlesfichiersdentte,
consulterleChapitre5.Pourlinstant,sachezseulementquilfautajouterlalignesuivante:
#include <stdarg.h>

audbutdevotreprogramme. Celapermetdutiliserletypeva_listetlesexpressions va_start,


va_arg et va_end pourrcuprerlesargumentsdelalistedeparamtresvariable,unun.
Leprincipeestsimple.Danslafonction,vousdevezdclarerunevariabledetypeva_list.Puis,vous
devezinitialisercettevariableaveclasyntaxesuivante:
va_start(variable,paramtre);

o variable estlenomdelavariabledetypeva_listquevousvenezdecrer,et paramtre estle


dernierparamtreclassiquedelafonction.Dsque variable estinitialise,vouspouvezrcuprer
ununlesparamtreslaidedelexpressionsuivante:
va_arg(variable,type)

quirenvoieleparamtreencoursavecletypetypeetmetjour variable pourpasserauparamtre


suivant.Vouspouvezutilisercetteexpressionautantdefoisquevousledsirez,elleretournechaque
foisunnouveauparamtre. Lorsquelenombredeparamtrescorrect atrcupr, vousdevez
dtruirelavariablevariablelaidedelasyntaxesuivante:
va_end(variable);

17

Chapitre1.PremireapprocheduC/C++
Ilestpossiblederecommencercestapesautantdefoisquelonveut,laseulechosequicompteest
debienfairelinitialisationavec va_start etdebienterminerlaprocdureavec va_end chaque
fois.
Note:Il existeunerestrictionsurlestypesdesparamtresdeslistesvariablesdarguments.
Lorsdelappel desfonctions, uncertainnombredetraitementsalieusurlesparamtres. En
particulier,despromotionsimplicitesont lieu, cequi setraduit parlefait quelesparamtres
rellementpasssauxfonctionsnesontpasdutypedclar.Lecompilateurcontinuedefaireles
vrificationsdetype,maiseninterne,untypeplusgrandpeuttreutilispourpasserlesvaleurs
desparamtres.Enparticulier,lestypescharetshortnesontpasutiliss:lesparamtressont
toujourspromusauxtypeint oulongint. Celaimpliquequelesseulstypesquevouspouvez
utilisersontlestypesciblesdespromotionsetlestypesqui nesontpassujetsauxpromotions
(pointeurs,structuresetunions).Lestypesciblesdanslespromotionssontdterminscomme
suit:
lestypeschar,signedchar,unsignedchar,shortintouunsignedshortintsontpromusenint

si cetypeest capabledacceptertoutesleursvaleurs. Si int est insuffisant,unsignedint est


utilis;
lestypesdesnumrations(voirplusloinpourladfinitiondesnumrations)etwchar_tsont

promusenint, unsignedint, longouunsignedlongselonleurscapacits.


capabledeconserverlaplagedevaleurdutypepromouvoirestutilis;

Lepremiertype

lesvaleursdeschampsdebitssontconvertiesenintouunsignedintselonlatailleduchamp

debit(voirplusloinpourladfinitiondeschampsdebits);
lesvaleursdetypefloatsontconvertiesendouble.

Exemple120.Fonctionnombredeparamtresvariable
#include <stdarg.h>
/*Fonctioneffectuantlasommede"compte"paramtres:*/
doublesomme(intcompte,...)
{
doubleresultat=0;
/*Variablestockantlasomme.*/
va_listvarg;
/*Variableidentifiantleprochain
paramtre.*/
va_start(varg,compte);/*Initialisationdelaliste.*/
do
/*Parcoursdelaliste.*/
{
resultat=resultat+va_arg(varg,double);
compte=compte1;
}while(compte!=0);
va_end(varg);
/*Terminaison.*/
returnresultat;
}

Lafonction somme effectuelasommedecompteflottants(float


oudouble)et larenvoiedansun
double.Pourplusdedtailssurlastructuredecontrle do...while,voirSection2.4.

18

Chapitre1.PremireapprocheduC/C++

1.7.Lafonctionmain
Lorsquunprogrammeestcharg, sonexcutioncommenceparlappeldunefonctionspcialedu
programme.Cettefonctiondoitimprativementsappeler main (principalenanglais)pourque
lecompilateurpuissesavoirquecestcettefonctionquimarqueledbutduprogramme.Lafonction
main estappeleparlesystmedexploitation,ellenepeutpastreappeleparleprogramme,cest
direquellenepeutpastrercursive.
Exemple121.Programmeminimal
intmain()
/*PluspetitprogrammeC/C++.*/
{
return0;
}

Lafonction main doitrenvoyeruncodederreurdexcutionduprogramme,letypedececodeest


int.Ellepeutaussirecevoirdesparamtresdusystmedexploitation.Ceciseraexpliquplusloin.
Pourlinstant,onsecontenteradunefonctionmainneprenantpasdeparamtre.
main nedoitpasrenvoyerletypevoid.
Note:IlestspcifidanslanormeduC++quelafonction
Enpratiquecependant,beaucoupdecompilateurslacceptentgalement.

Lavaleur 0 retourneparlafonctionmain indiquequetoutsestdroulcorrectement.Enralit,


lavaleurducodederetourpeut treinterprtediffremment selonlesystmedexploitation
utilis.LabibliothqueCdfinitdonclesconstantesEXIT_SUCCESS et EXIT_FAILURE ,quiperme
ttentdesupprimerlhypothsesurlavaleurutiliserrespectivementencasdesuccsetencas
derreur.

1.8.Lesfonctionsdentre/sortiedebase
Nousavonsdistinguaudbutdecechapitrelesprogrammesgraphiques,quitraitentlesvnements
quilsreoivent dusystmesouslaformedemessages, desautresprogrammes, qui reoivent les
donnestraiteretcriventleursrsultatssurlesfluxdentre/sortiestandards.Lesnotionsdeflux
dentre/sortiestandardsnontpastdfiniesplusendtailcemoment,etilesttempsprsent
depalliercettelacune.

1.8.1.Gnralitssurlesfluxdentre/sortieenC
Unfluxestunenotioninformatiquequipermetdereprsenterunflotdedonnessquentiellesen
provenancedunesourcededonnesoudestinationduneautrepartiedusystme.
Lesfluxsont
utilisspouruniformiserlamaniredontlesprogrammestravaillentaveclesdonnes,etdoncpour
simplifierleurprogrammation.Lesfichiersconstituentunbonexempledeflux,maiscenestpasle
seultypedefluxexistant:onpeuttraiterunfluxdedonnesprovenantdunrseau,
duntampon
mmoireoudetouteautresourcededonnesoupartiedusystmepermettantdetraiterlesdonnes
squentiellement.
Surquasimenttouslessystmesdexploitation,lesprogrammesdisposentdsleurlancementdetrois
fluxdentre/sortiestandards.Gnralement,lefluxdentrestandardestassociaufluxdedonnes
provenantdunterminal,etlefluxdesortiestandardlaconsoledeceterminal.Ainsi,lesdonnes
quelutilisateursaisitauclavierpeuventtreluesparlesprogrammessurleurfluxdentrestandard,

19

Chapitre1.PremireapprocheduC/C++
etilspeuventafficherleursrsultatslcranencrivantsimplementsurleurfluxdesortiestandard.
Letroisimefluxstandardestlefluxderreurstandardqui,pardfaut,estgalementassocilcran,
etsurlequelleprogrammepeutcriretouslesmessagesderreurquildsire.
Note:Laplupartdessystmespermettentderedirigerlesfluxstandardsdesprogrammesafin
delesfairetravaillersurdesdonnesprovenantduneautresourcededonnesqueleclavier,
ou, parexemple, deleurfaireenregistrerleursrsultatsdansunfichier. Il est mmecourant
deraliserdespipelinesdeprogrammes,olesrsultatsdelunsontenvoysdansleflux
dentrestandarddelautre,etainsidesuite.Cessuitesdeprogrammessontgalementappels
des tubesenfranais.
Lamanirederaliserlesredirectionsdesfluxstandardsdpenddessystmesdexploitationet
deleursinterfacesutilisateurs.Deplus,lesprogrammesdoiventtrecapablesdetravailleravec
leursfluxdentre/sortiestandardsdemaniregnrique,queceuxcisoientredirigsounon.
Lestechniquesderedirectionneserontdoncpasdcritesplusendtailici.
Vousremarquerezlintrtdavoirdeuxfluxdistinctspourlesrsultatsdesprogrammesetleurs
messagesderreur. Si, lorsduneutilisationnormale, cesdeuxfluxsemlangent lcran, ce
nestpaslecaslorsquelonredirigelefluxdesortiestandard.Seullefluxderreurstandardest
affichlcrandanscecas,etlesmessagesderreurnesemlangentdoncpasauxrsultats
duprogramme.
Onpourrait penser quelesprogrammesgraphiquesnedisposent pasdefluxdentre/ sor
tiestandards.Pourtant,cestgnralementlecas.Lesvnementstraitsparlesprogrammes
graphiquesdansleurboucledemessagesneproviennent gnralement pasdufluxdentre
standard,maisduneautresourcededonnesspcifiquechaquesystme.Enconsquence,
lesprogrammesgraphiquespeuvent toujoursutiliserlesfluxdentre/ sortiestandardsi cela
savrencessaire.

Afindepermettreauxprogrammesdcriresurleursfluxdentre/sortiestandards,labibliothque
Cdfinitplusieursfonctionsextrmementutiles.Lesdeuxprincipalesfonctionssontsansdouteles
fonctions printf et scanf.Lafonction printf (printformattedenanglais)permetdafficher
desdonneslcran,et scanf (scanformatted)permetdeleslirepartirduclavier.
Enralit,cesfonctionsnefontriendautrequedappelerdeuxautresfonctionspermettantdcrire
etdeliredesdonnessurunfichier:lesfonctions fprintf et fscanf. Cesfonctionssutilisent
exactementdelammemanirequelesfonctions printf et scanf,ceciprsquellesprennenten
premierparamtreunestructuredcrivantlefichiersurlequelellestravaillent.Pourlesfluxdentre/
sortiestandards,labibliothqueCdfinitlespseudofichiers stdin, stdout et stderr,quicorres
pondentrespectivementauxfluxdentre,aufluxdesortieetaufluxderreurstandards.Ainsi,tout
appel scanf setraduitparunappel fscanf surlepseudofichier stdin,ettoutappel printf
parunappel fprintf surlepseudofichier stdout.
Note:Il nexistepasdefonctionpermettant dcriredirectement surlefluxderreurstandard.
Parconsquent,poureffectuerdetellescritures,il fautimprativementpasserparlafonction
fprintf,enluifournissantenparamtrelepseudofichierstderr.
LadescriptiondesfonctionsdelabibliothqueCstandarddpassedeloinlecadredececours.
Aussi lesfonctionsdelectureet dcrituresurlesfichiersneserontellespasdcritesplusen
dtail ici.Seuleslesfonctions printf et scanf serontprsentes,carellessontrellementin
dispensablepourlcrituredunprogrammeC.Consultezlabibliographiesivousdsirezobtenir
plusdedtailssurlabibliothqueCetsurtouteslesfonctionsquellecontient.
LeC++disposegalement demcanismesdegestiondesfluxdentre/
sortiequi lui sont
propres.Cesmcanismespermettentdecontrlerplusfinementlestypesdesdonnescrites
etluesdeetpartirdesfluxdentre/sortiestandards.Deplus,ilspermettentderaliserles
oprationsdcritureet delecturedesdonnesformatesdemanirebeaucoupplussimple.

20

Chapitre1.PremireapprocheduC/C++
Cependant, cesmcanismesrequirent desnotionsobjetsavanceset neseront dcritsque
printf
dansleschapitresddisauC++.Commeilestgalementpossibledutiliserlesfonctions
et scanf enC++dunepart,etque,dautrepart,cesfonctionssontessentiellesenC,lasuitede
cettesectionsattacheraleurdescription.Unchapitrecompletestddiauxmcanismesde
gestiondesfluxduC++dansladeuximepartiedecedocument.

Lesfonctions printf et scanf sonttoutesdeuxdesfonctionsnombredeparamtresvariables.


Ellespeuventdonctreutilisespoureffectuerdescrituresetdeslecturesmultiplesenunseulappel.
Afindeleurpermettrededterminerlanaturedesdonnespassesdanslesargumentsvariables,elles
attendenttouteslesdeuxenpremierparamtreunechanedecaractresdescriptivedesarguments
suivants.Cettechaneestappelechanedeformat,etellepermetdespcifieravecprcisionletype,
lapositionetlesoptionsdeformat(prcision,etc.)desdonnestraiter.Lesdeuxsectionssuivantes
dcrivent lamaniredutiliserceschanesdeformat pourchacunedesdeuxfonctions printf et
scanf.

1.8.2.Lafonctionprintf
Lafonction printf semploiecommesuit:
printf(chanedeformat[,valeur[,valeur[...]]])

Onpeutpasserautantdevaleursquelonveut, pourpeuquellessoienttoutesrfrencesdansla
chanedeformat.Ellerenvoielenombredecaractresaffichs.
Lachanedeformatpeutcontenirdutexte,maissurtoutelledoitcontenirautantdeformateursque
devariablesafficher.Sicenestpaslecas,leprogrammeplantera.Lesformateurssontplacsdans
letextelolesvaleursdesvariablesdoiventtreaffiches.
Lasyntaxedesformateursestlasuivante:
%[[indicateur]...][largeur][.prcision][taille]type

Unformateurcommencedonctoujoursparlecaractre%.
formateur,ilfautleddoubler(%%).

Pouraffichercecaractresansfaireun

Letypedelavariableafficherestobligatoireluiaussi.Lestypesutilisablessontlessuivants:
Tableau11.Typespourleschanesdeformatdeprintf
Typededonneafficher
Numriques

Caractres

Caractredeformatage

Entierdcimalsign

Entierdcimalnonsign

uoui

Entieroctalnonsign

Entierhexadcimalnonsign

x(aveclescaractresaf)ouX
(aveclescaractresAF)

Flottantsdetypedouble

f,e,g,EouG

Caractreisol

Chanedecaractres

21

Chapitre1.PremireapprocheduC/C++
Typededonneafficher
Pointeurs

Pointeur

Caractredeformatage
p

Note:VoirleChapitre4pourplusdedtailssurlespointeurs.Leformatdespointeursdpend
delamachine.
Lesvaleursflottantesinfiniessontremplacesparlesmentions +INF et INF.Unnonnombre
IEEE(NotANumber)donne +NAN ou NAN.NotezquelestandardCnepermetdeformaterque
desvaleursdetypedouble.Lesvaleursflottantesdetypefloatdevrontdonctreconvertieen
doubleavantaffichage.

Lesautresparamtressontfacultatifs.
Lesvaleursdisponiblespourleparamtredetaillesontlescaractressuivants:
Tableau12.Optionspourlestypesdeschanesdeformat
Option

Typeutilisable

Tailledutype

Pointeur

PointeurFAR(DOSuniquement)

Pointeur

PointeurNEAR(DOSuniquement)

Entier

shortint

Entier,caractreouchane
decaractres

longintouwchar_t

Flottant

longdouble

Exemple122.Utilisationdeprintfetfprintf
#include <stdio.h>

/*Nepascherchercomprendrecetteligne
pourlinstant.Elleestncessairepourutiliser
lesfonctionsprintfetscanf.
*/

intmain(void)
{
inti=2;
printf("Voicilavaleurdei:%d.\n",i);
/*Exempledcrituresurlasortiederreurstandard:*/
fprintf(stderr,"Pasderreurjusquici...\n");
return0;
}

Vousremarquerezdanscet exemplelaprsenceduneligne #include <stdio.h>. Cetteligne


estncessairepourpermettrelutilisationdesfonctions printf et fprintf.Nousdcrironssasi
gnificationprciseultrieurementdanslechapitresurleprprocesseur.Sansentrerdanslesdtails,
disonssimplementquecettelignepermetdinclureunfichiercontenantlesdclarationsdetoutesles
fonctionsdentre/sortiedebase.
Lesparamtres indicateurs , largeur et prcision sontmoinsutiliss.Ilpeutyavoirplu
sieursparamtresindicateurs, ilspermettent demodifierlapparencedelasortie. Lesprincipales
optionssont:

22

Chapitre1.PremireapprocheduC/C++

:justificationgauchedelasortie,avecremplissagedroitepardes0oudesespaces;

+:affichagedusignepourlesnombrespositifs;

espace:lesnombrespositifscommencenttousparunespace.

Leparamtre largeur permetdespcifierlalargeurminimaleduchampdesortie,silasortieest


troppetite,oncomplteavecdes0oudesespaces.Notezquilsagitbiendunelargeurminimaleici
etnondunelargeurmaximale.Lersultatduformatagedeladonnecrirepeutdoncdpasserla
valeurindiquepourlalargeurduchamp.
Enfin, leparamtre prcision
afficher).

spcifielaprcisionmaximaledelasortie(nombredechiffres

1.8.3.Lafonctionscanf
Lafonction scanf permetdefaireuneouplusieursentres.Commelafonction printf,elleattend
unechanedeformatenpremierparamtre. Ilfautensuitepasserlesvariablesdevantcontenirles
entresdanslesparamtresquisuivent.Sasyntaxeestlasuivante:
scanf(chanedeformat,&variable[,&variable[...]]);

Ellerenvoielenombredevariableslues.
Necherchezpascomprendrepourlinstantlasignificationdusymbole& setrouvantdevantchacune
desvariables.Sachezseulementquesilestoubli,leprogrammeplantera.
Lachanedeformatpeutcontenirdeschanesdecaractres.Toutefois,siellecontientautrechoseque
desformateurs,letextesaisiparlutilisateurdevracorrespondreimprativementavecleschanesde
caractresindiquesdanslachanedeformat. scanf chercherareconnatreceschanes,etarrtera
lanalyselapremireerreur.
Lasyntaxedesformateurspour scanf diffreunpeudecelledeceuxde

printf :

%[*][largeur][taille]type

Seulleparamtre largeur changeparrapport printf.Ilpermetdespcifierlenombremaximal


decaractresprendreencomptelorsdelanalyseduparamtre.Leparamtre*estfacultatif,il
indiqueseulementdepasserladonneentreetdenepaslastockerdanslavariabledestination.Cette
variabledoitquandmmetreprsentedanslalistedesparamtresde scanf.
Note:Tout commepourlesfonctions printf et fprintf, il est ncessairedajouterlaligne
#include <stdio.h> endbutdefichierpourpouvoirutiliserlafonctionscanf.Lasignification
decetteligneseradonnedanslechapitretraitantduprprocesseur.
Enpratique,lafonction scanf nanalyselescaractresprovenantdufluxdentrequelorsquune
lignecomplteatsaisie.Toutefois,ellenesupprimepasdutampondefluxdentrelecarac
tredesautdeligne,si bienquil sytrouveratoujourslorsdelentresuivante.Celanestpas
gnantsi lonnutilisequelafonction scanf pourraliserlesentresdedonnesdanslepro
gramme,carcettefonctionignoretoutsimplementcescaractresdesautdeligne.Enrevanche,
si lonutiliseuneautrefonctionaprsunappel scanf,il fautsattendretrouvercecaractre
desautdelignedanslefluxdentre.

23

Chapitre1.PremireapprocheduC/C++
Lafonction scanf nestpastrsadaptelalecturedeschanesdecaractres,caril
nestpas
faciledecontrlerlataillemaximalequelutilisateurpeutsaisir.Cestpourcetteraisonquelon
agnralement recourslafonction fgets, qui permet delireunelignesurlefluxdentre
standardetdestockerlersultatdansunechanedecaractresfournieenpremierparamtre
etdontlalongueurmaximaleestspcifieendeuximeparamtre.Letroisimeparamtrede
lafonction fgets est lefluxpartirduquel lalecturedelalignedoit treralise, cest dire
gnralement stdin.Lanalysedelachanedecaractresainsiluepeutalorstrefaiteavecune
fonctionsimilairelafonction scanf,maisqui litlescaractresanalyserdansunechanede
caractresaulieudelesliredirectement depuislefluxdentrestandard: lafonction sscanf.
Cettefonctionsutiliseexactementcommelafonction scanf,ceci prsquil fautlui fourniren
premierparamtrelachanedecaractresdanslaquellesetrouventlesdonnesinterprter.
Ladescriptiondecesdeuxfonctionsdpasselecadredecedocumentetneseradoncpasfaite
ici.Veuillezvousrfrerladocumentationdevotreenvironnementdedveloppementoula
bibliographiepourplusdedtailsleursujet.

1.9.Exempledeprogrammecomplet
Leprogrammesuivantestdonntitredexemple.Ilcalculelamoyennededeuxnombresentrsau
clavieretlaffiche:
Exemple123.Programmecompletsimple
#include <stdio.h>

/*Autoriselemploideprintfetdescanf.*/

longdoublex,y;
intmain(void)
{
printf("Calculdemoyenne\n");
/*Afficheletitre.*/
printf("Entrezlepremiernombre:");
scanf("%Lf",&x);
/*Entrelepremiernombre.*/
printf("\nEntrezledeuximenombre:");
scanf("%Lf",&y);
/*Entreledeuximenombre.*/
printf("\nLavaleurmoyennede%Lfetde%Lfest%Lf.\n",
x,y,(x+y)/2);
return0;
}

Danscetexemple,leschanesdeformatspcifientdesflottants(f)enquadrupleprcision(L).

24

Chapitre2.Lesstructuresdecontrle
Nousallonsaborderdanscechapitreunautreaspectdulangageindispensablelaprogrammation,
savoir:lesstructuresdecontrle.Cesstructurespermettent,commeleurnomlindique,decontrler
lexcutionduprogrammeenfonctiondecritresparticuliers. LeCetleC++disposentdetoutes
lesstructuresdecontrleclassiquesdeslangagesdeprogrammationcommelestests,lesboucles,les
sauts,etc.Toutescesstructuressontdcritesdanslessectionssuivantes.

2.1.Lastructureconditionnelleif
Lastructureconditionnelle if permetderaliseruntestetdexcuteruneinstructionounonselonle
rsultatdecetest.Sasyntaxeestlasuivante:
if(test)opration;

o test estuneexpressiondontlavaleurestboolenneouentire.Toutevaleurnonnulleestconsi
drecommevraie.Siletestestvrai, opration estexcut.Cepeuttreuneinstructionouunbloc
dinstructions.Unevariantepermetdespcifierlactionexcuterencasdetestfaux:
if(test)opration1;
elseopration2;

Note:Attention!Lesparenthsesautourdutestsontncessaires!

Lesoprateursdecomparaisonsontlessuivants:
Tableau21.Oprateursdecomparaison
==

galit

!=

ingalit

<

infriorit

>

supriorit

<=

infrioritougalit

>=

suprioritougalit

Lesoprateurslogiquesapplicablesauxexpressionsboolennessontlessuivants:
Tableau22.Oprateurslogiques
&&

etlogique

||

oulogique

ngationlogique

25

Chapitre2.Lesstructuresdecontrle
Ilnyapasdoprateurouexclusiflogique.
Exemple21.Testconditionnelif
if(a<b&&a!=0)
{
m=a;
nouveau_m=1;
}

2.2.Labouclefor
Lastructuredecontrle for estsansdoutelunedesplusimportantes.Ellepermetderalisertoutes
sortesdeboucleset,enparticulier,lesbouclesitrantsurlesvaleursdunevariabledecontrle.Sa
syntaxeestlasuivante:
for(initialisation;test;itration)opration;

o initialisation estuneinstruction(ouunblocdinstructions)excuteavantlepremierpar
coursdelaboucledu for. test estuneexpressiondontlavaleurdtermineralafindelaboucle.
itration estloprationeffectuerenfindeboucle,et opration constitueletraitementdela
boucle.Chacunedecespartiesestfacultative.
Lasquencedexcutionestlasuivante:
initialisation
test:sautenfinduforousuite
opration
itration
retourautest
findufor.

Exemple22.Bouclefor
somme=0;
for(i=0;i <=10;i=i+1)somme=somme+i;
Note:EnC++,il estpossiblequelapartieinitialisation dclareunevariable.Danscecas,
for.Parexemple,
lavariabledclarenestdfiniequlintrieurdelinstruction
for(inti=0;i <10;++i);

eststrictementquivalent:
{
inti;
for(i=0;i <10;++i);
}

26

Chapitre2.Lesstructuresdecontrle
Celasignifiequelonnepeut pasutiliserlavariable i aprslinstruction for, puisquellenest
dfiniequedanslecorpsdecetteinstruction.Celapermetderaliserdesvariablesmuettesqui
neserventqulinstructionfor danslaquelleellessontdfinies.

Note:Cetterglenest pascelleutiliseparlaplupart descompilateursC++. Larglequils


initialisation delinstructionfor reste
utilisentspcifiequelavariabledclaredanslapartie
dclareaprscetteinstruction.Ladiffrenceestsubtile,maisimportante.Celaposeassurment
desproblmesdecompatibilitaveclesprogrammesC++critspourcescompilateurs,puisque
dansuncaslavariabledoit treredclareet danslautrecaselleneledoit pas. Il est donc
recommanddenepasdclarerdevariablesdanslapartie initialisation desinstructions
for pourassureruneportabilitmaximale.

2.3.Lewhile
Le while permetdexcuterdesinstructionsenboucletantquuneconditionestvraie.Sasyntaxeest
lasuivante:
while(test)opration;

o opration esteffectuetantque test estvrifi.Commepourle if,lesparenthsesautourdu


testsontncessaires.Lordredexcutionest:
test
opration

Exemple23.Bouclewhile
somme=i=0;
while(somme<1000)
{
somme=somme+2*i/(5+i);
i=i+1;
}

2.4.Ledo
Lastructuredecontrle do permet,toutcommele while,deraliserdesbouclesenattentedune
condition.Cependant,contrairementceluici,ledo effectueletestsurlaconditionaprslexcution
desinstructions.Celasignifiequelesinstructionssonttoujoursexcutesaumoinsunefois,quele
testsoitvrifiounon.Sasyntaxeestlasuivante:
doopration;
while(test);
opration esteffectuejusquceque

test nesoitplusvrifi.

Lordredexcutionest:

27

Chapitre2.Lesstructuresdecontrle
opration
test

Exemple24.Boucledo
p=i=1;
do
{
p=p*i;
i=i+1;
}while(i!=10);

2.5.Lebranchementconditionnel
Danslecasoplusieursinstructionsdiffrentesdoiventtreexcutesselonlavaleurdunevariable
detypeintgral,lcriturede if successifspeuttrerelativementlourde.LeC/C++fournitdoncla
structuredecontrle switch,quipermetderaliserunbranchementconditionnel.Sasyntaxeestla
suivante:
switch(valeur)
{
casecas1:
[instruction;
[break;]
]
casecas2:
[instruction;
[break;]
]
.
.
.
casecasN:
[instruction;
[break;]
]
[default:
[instruction;
[break;]
]
]
}

valeur estvaluenpremier.Sontypedoittreentier.Selonlersultatdelvaluation,lexcution
default est
duprogrammesepoursuitaucasdemmevaleur.Siaucundescasnecorrespondetsi
prsent,lexcutionsepoursuitaprs default.Sienrevanche default nestpasprsent,onsortdu
switch.

Lesinstructionsqui suivent le case appropriou default sont excutes. Puis, lesinstructions


switch).Pourforcerlasortiedu
ducassuivantsontgalementexcutes(onnesortdoncpasdu
switch,ondoitutiliserlemotcl break.

28

Chapitre2.Lesstructuresdecontrle
Exemple25.Branchementconditionnelswitch
i=2;
switch(i)
{
case1:
case2:
/*Sii=1ou2,lalignesuivanteseraexcute.*/
i=2i;
break;
case3:
i=0;
/*Cetteligneneserajamaisexcute.*/
default:
break;
}
Note:Ilestinterditdeffectuerunedclarationdevariabledansundescase dun switch.

2.6.Lesaut
LeC/C++disposeduneinstructiondesautpermettantdepoursuivrelexcutionduprogrammeen
unautrepoint. Bienquilsoitfortementdconseilldelutiliser, cetteinstructionestncessaireet
peutparfoistretrsutile,notammentdanslestraitementsderreurs.Sasyntaxeestlasuivante:
gototiquette;

o tiquette estunetiquettemarquantlalignedestinationdanslafonction.Lestiquettessont
simplementdclaresaveclasyntaxesuivante:
tiquette:

Lestiquettespeuventavoirnimportequelnomdidentificateur.
Il nest paspossibledeffectuerdessautsendehorsdunefonction.
Enrevanche, il est possible
deffectuerdessautsendehorset lintrieurdesblocsdinstructionssouscertainesconditions.
Si ladestinationdusaut setrouveaprsunedclaration, cettedclarationnedoit pascomporter
dinitialisations.Deplus,cedoittreladclarationduntypesimple(cestdireunedclarationqui
nedemandepaslexcutiondecode)commelesvariables,lesstructuresoulestableaux.Enfin,si,au
coursdunsaut,lecontrledexcutionsortdelaportedunevariable,celleciestdtruite.
Note:CesderniresrglessontparticulirementimportantesenC++silavariableestunobjet
dont laclasseaunconstructeurouundestructeurnontrivial. VoirleChapitre8pourplusde
dtailscesujet.
AutrerglespcifiqueauC++:ilestimpossibledeffectuerunsautlintrieurdunblocdecode
enexcutionprotge try{}.VoiraussileChapitre9concernantlesexceptions.

29

Chapitre2.Lesstructuresdecontrle

2.7.Lescommandesderupturedesquence
Enplusdu goto vuprcdemment,ilexistedautrescommandesderupturedesquence(cestdire
dechangementdelasuitedesinstructionsexcuter).Cescommandessontlessuivantes:
continue;

ou
break;

ou
return[valeur];

return permetdequitterimmdiatementlafonctionencours.Commeonladjvu,lacommande
return peutprendreenparamtrelavaleurderetourdelafonction.
break permetdepasserlinstructionsuivantlinstruction

while, do, for ou switch laplusim

brique(cestdirecelledanslaquelleonsetrouve).
continue sautedirectementladernirelignedelinstruction while, do ou for laplusimbrique.
Cetteligneestlaccoladefermante.Cestceniveauquelestestsdecontinuationsontfaitspour for
et do, ouquelesautaudbutdu while esteffectu(suiviimmdiatementdutest).Onrestedonc
danslastructuredanslaquelleonsetrouvaitaumomentdelexcutionde continue,contrairement
cequisepasseavecle break.

Exemple26.Rupturedesquenceparcontinue
/*Calculelasommedes1000premiersentierspairs:*/
somme_pairs=0;
for(i=0;i <1000;i=i+1)
{
if(i%2==1)continue;
somme_pairs=somme_pairs+i;
}

30

Chapitre3.Typesavancsetclassesde
stockage
LelangageC/C++permetladfinitiondetypespersonnalissconstruitspartirdestypesdebase
dulangage.Outrelestableaux,quelonadjprsents,ilestpossiblededfinirdiffrentstypesde
donnesvolus,principalementlaidedelanotiondestructure.Parailleurs,lesvariablesdclares
dansunprogrammesedistinguent,outreparleurtype,parcequelonappelleleurclassedestockage.
Lapremiresectiondecechapitretraiteradoncdelamaniredontonpeutcreretmanipulerde
nouveauxtypesdedonnesenC/C++, etladeuximesectionprsenteralesdiffrentesclassesde
stockageexistantesetleursignificationprcise.

3.1.Structuresdedonnesettypescomplexes
Endehorsdestypesdevariablessimples,leC/C++permetdecrerdestypespluscomplexes.Ces
typescomprennentessentiellementlesstructures,lesunionsetlesnumrations,maisilestgalement
possiblededfinirdenouveauxtypespartirdecestypescomplexes.

3.1.1.Lesstructures
Lestypescomplexespeuvent seconstruirelaidedestructures. Pourcela, onutiliselemot cl
struct.Sasyntaxeestlasuivante:
struct[nom_structure]
{
typechamp;
[typechamp;
[...]]
};

Ilnestpasncessairededonnerunnomlastructure.Lastructurecontientplusieursautresvariables,
appeleschamps.Leurtypeestdonndansladclarationdelastructure.Cetypepeuttrenimporte
quelautretype,mmeunestructure.
Lastructureainsidfiniepeutalorstreutilisepourdfinirunevariabledontletypeestcettestruc
ture.
Pourcela,deuxpossibilits:

fairesuivreladfinitiondelastructureparlidentificateurdelavariable;
Exemple31.Dclarationdevariabledetypestructure
structClient
{
unsignedcharAge;
unsignedcharTaille;
}Jean;

ou,plussimplement:

31

Chapitre3.Typesavancsetclassesdestockage
struct
{
unsignedcharAge;
unsignedcharTaille;
}Jean;

Dansledeuximeexemple,lenomdelastructurenestpasmis.

dclarerlastructureenluidonnantunnom,puisdclarerlesvariablesaveclasyntaxesuivante:
[struct]nom_structureidentificateur;

Exemple32.Dclarationdestructure
structClient
{
unsignedcharAge;
unsignedcharTaille;
};
structClientJean,Philippe;
ClientChristophe;
//ValideenC++maisinvalideenC

Danscet exemple, lenomdelastructuredoit tremis, caronutilisecettestructurelaligne


suivante. Pourladclarationdesvariables Jean et Philippe detypestruct Client, lemot cl
struct atmis. Celanest pasncessaireenC++, maislest enC. LeC++permet doncde
dclarerdesvariablesdetypestructureexactementcommesiletypestructuretaituntypeprdfini
dulangage.Ladclarationdelavariable Christophe cidessusestinvalideenC.

Leslmentsdunestructuresont accdsparunpoint, suivi dunomduchampdelastructure


accder.Parexemple,lgede Jean estdsignpar Jean.Age.
Note:LetypageduC++estplusfortqueceluiduC,parcequilconsidrequedeuxtypesnesont
identiquesquesilsontlemmenom.AlorsqueleCconsidrequedeuxtypesquiontlamme
structuresontdestypesidentiques,leC++lesdistingue.Celapeuttreuninconvnient,cardes
programmesqui pouvaient trecompilsenCneleseront pasforcment paruncompilateur
C++.Considronslexemplesuivant:
intmain(void)
{
structst1
{
inta;
}variable1={2};
struct
{
inta;
}variable2;
/*variable2aexactementlammestructure
quevariable1,*/
variable2=variable1;
/*maiscelaestILLGALenC++!*/
return0;
}

32

Chapitre3.Typesavancsetclassesdestockage

Bienquelesdeuxvariablesaientexactementlammestructure,ellessontdetypediffrents!
Eneffet, variable1 estdetypest1,et variable2 detype(lastructurequiapermisdela
construirenapasdenom).Onnepeutdoncpasfairelaffectation.Pourtant,ceprogrammetait
compilableenCpur...

Note:Il estpossibledenepasdonnerdenomunestructurelorsdesadfinitionsanspour
autantdclarerunevariable.Detellesstructuresanonymesnesontutilisablesquedanslecadre
dunestructureinclusedansuneautrestructure:
structstruct_principale
{
struct
{
intchamp1;
};
intchamp2;
};

Danscecas, leschampsdesstructuresimbriquesseront accdscommesil sagissait de


champsdelastructureprincipale. Laseulelimitationest que, bienentendu, il nyait pasde
conflitentrelesnomsdeschampsdesstructuresimbriquesetceuxdeschampsdelastructure
principale.Silyaconflit,ilfautdonnerunnomlastructureimbriquequiposeproblme,enen
faisantunvraichampdelastructureprincipale.

3.1.2.Lesunions
Lesunionsconstituentunautretypedestructure.Ellessontdclaresaveclemotcl union,quia
lammesyntaxeque struct.Ladiffrenceentrelesstructuresetlesunionsestquelesdiffrents
champsduneunionoccupentlemmeespacemmoire.Onnepeutdonc,toutinstant,nutiliser
quundeschampsdelunion.
Exemple33.Dclarationduneunion
unionentier_ou_reel
{
intentier;
floatreel;
};
unionentier_ou_reelx;
x peutprendrelaspectsoitdunentier,soitdunrel.Parexemple:
x.entier=2;

affectelavaleur 2 x.entier,cequidtruit x.reel.


Si,prsent,onfait:

33

Chapitre3.Typesavancsetclassesdestockage
x.reel=6.546;

lavaleurde x.entier estperdue,carlerel 6.546 atstockaummeemplacementmmoireque


lentier x.entier.
Lesunions,contrairementauxstructures,sontassezpeuutilises,saufenprogrammationsystmeo
londoitpouvoirinterprterdesdonnesdediffrentesmaniresselonlecontexte.Danscecas,on
auraavantageutiliserdesunionsdestructuresanonymesetaccderauxchampsdesstructures,
chaquestructurepermettantdemanipulerlesdonnesselonunedeleursinterprtationspossibles.
Exemple34.Unionavecdiscriminant
structSystemEvent
{
intiEventType;

/*Discriminantdelvnement.
Permetdechoisircommentlinterprter.*/

union
{
struct
{
intiMouseX;
intiMouseY;
};
struct
{
charcCharacter;
intiShiftState;
};
/*etc.*/
};

/*Structurepermettantdinterprter*/
/*lesvnementssouris.*/

/*Structurepermettantdinterprter*/
/*lesvnementsclavier.*/

};
/*Exempledutilisationdesvnements:*/
intProcessEvent(structSystemEvente)
{
intresult;
switch(e.iEventType)
{
caseMOUSE_EVENT:
/*Traitementdelvnementsouris...*/
result=ProcessMouseEvent(e.iMouseX,e.iMouseY);
break;
caseKEYBOARD_EVENT:
/*Traitementdelvnementclavier...*/
result=ProcessKbdEvent(e.cCharacter,e.iShiftState);
break;
}
returnresult;
}

34

Chapitre3.Typesavancsetclassesdestockage

3.1.3.Lesnumrations
Lesnumrationssontdestypesintgraux(cestdirequilssontbasssurlesentiers),pourlesquels
chaquevaleurdisposedunnomunique.Leurutilisationpermetdedfinirlesconstantesentiresdans
unprogrammeetdelesnommer.Lasyntaxedesnumrationsestlasuivante:
enumenumeration
{
nom1[=valeur1]
[,nom2[=valeur2]
[...]]
};

Danscettesyntaxe, enumeration reprsentelenomdelnumrationet nom1, nom2, etc. repr


sententlesnomsdesnumrs.Pardfaut,lesnumrsreoiventlesvaleursentires 0, 1,etc.sauf
siunevaleurexpliciteleurestdonnedansladclarationdelnumration.Dsquunevaleurestdon
ne,lecompteurdevaleurssesynchroniseaveccettevaleur,sibienquelnumrsuivantprendra
pourvaleurcelledelnumrprcdentaugmentede 1.
Exemple35.Dclarationdunenumration
enumNombre
{
un=1,deux,trois,cinq=5,six,sept
};

Danscetexemple, lesnumrsprennentrespectivementleursvaleurs.
dfini,uneresynchronisationalieulorsdeladfinitionde cinq.

Comme quatre nestpas

Lesnumrationssuivent lesmmesrglesquelesstructureset lesunionsencequi concernela


dclarationdesvariables:ondoitrpterlemotcl enum enC,cenestpasncessaireenC++.

3.1.4.Leschampsdebits
Ilestpossiblededfinirdeschampsdebitsetdedonnerdesnomsauxbitsdeceschamps.Pourcela,
onutiliseralemotcl struct etondonneraletypedesgroupesdebits,leursnoms,etenfinleurs
tailles:
Exemple36.Dclarationdunchampsdebits
structchamp_de_bits
{
intvar1;
intbits1a4 :4;
intbits5a10:6;
unsignedintbits11a16:6;
};

/*Dfinitunevariableclassique.*/
/*Premierchamp:4bits.*/
/*Deuximechamp:6bits.*/
/*Dernierchamp:6bits.*/

Latailledunchampdebitsnedoitpasexcdercelledunentier. Pouralleraudel, oncreraun


deuximechampdebits. Lamaniredont lesdiffrentsgroupesdebitssont
placsenmmoire
dpendducompilateuretnestpasnormalise.
Lesdiffrentsbitsougroupesdebitsseronttousaccessiblescommedesvariablesclassiquesdune
structureouduneunion:

35

Chapitre3.Typesavancsetclassesdestockage
structchamp_de_bitsessai;
intmain(void)
{
essai.bits1a4=3;
/*suiteduprogramme*/
return0;
}

3.1.5.Initialisationdesstructuresetdestableaux
Lestableauxetlesstructurespeuventtreinitialises,toutcommelestypesclassiquespeuventltre.
Lavaleurservantlinitialisationestdcriteenmettantlesvaleursdesmembresdelastructureoudu
tableauentreaccoladesetenlessparantpardesvirgules:
Exemple37.Initialisationdunestructure
/*DfinitletypeClient:*/
structClient
{
unsignedcharAge;
unsignedcharTaille;
unsignedintComptes[10];
};
/*DclareetinitialiselavariableJohn:*/
structClientJohn={35,190,{13594,45796,0,0,0,0,0,0,0,0}};

Lavariable John esticidclarecommetantdetypeClientetinitialisecommesuit:songeestde


35,sataillede 190 etsesdeuxpremierscomptesde 13594 et 45796.Lesautrescomptessontnuls.
Ilnestpasncessairederespecterlimbricationdutypecomplexeauniveaudesaccolades,
nide
fournirdesvaleursdinitialisationspourlesderniersmembresduntypecomplexe.Lesvaleurspar
dfautquisontutilisesdanscecassontlesvaleursnullesdutypeduchampnoninitialis.Ainsi,la
dclarationde John auraitpusefaireainsi:
structClientJohn={35,190,13594,45796};

Note:LanormeC99fournitgalementuneautresyntaxepluspratiquepourinitialiserlesstruc
tures. Cettesyntaxepermet dinitialiserlesdiffrentschampsdelastructureenlesnommant
explicitement et enleur affectant directement leur valeur. Ainsi, aveccettenouvellesyntaxe,
linitialisationprcdentepeuttreralisedelamaniresuivante:
Exemple38.InitialisationdestructureC99
/*DclareetinitialiselavariableJohn:*/
structClientJohn={
.Taille=190,
.Age=35,
.Comptes[0]=13594,
.Comptes[1]=45796

36

Chapitre3.Typesavancsetclassesdestockage
};

Onconstateraqueleschampsqui nesont pasexplicitement initialisssont, encoreunefois,


initialissleurvaleurnulle.Deplus,commelemontrecetexemple,il nestpasncessairede
respecterlordredapparitiondesdiffrentschampsdansladclarationdelastructurepourleur
initialisation.
Il estpossibledemlangerlesdeuxsyntaxes.Danscecas,lesvaleurspourlesquellesaucun
nomdechampnestdonnserontaffectesauchampssuivantsledernierchampnomm.De
plus, si plusieursvaleursdiffrentessont affectesaummechamp, seuleladernirevaleur
indiqueserautilise.
Cettesyntaxeestgalementdisponiblepourlinitialisationdestableaux.Danscecas,onutilis
eralescrochetsdirectement,sansdonnerlenomdutableau(exactementcommelinitialisation
desmembresdelastructureutilisedirectementlepoint,sansdonnerlenomdelastructureen
coursdinitialisation).OnnoteratoutefoisquecettesyntaxenestpasdisponibleenC++.Avecce
langage,il estprfrabledutiliserlanotiondeclasseetdedfinirunconstructeur.Lesnotions
declasseetdeconstructeurserontprsentesplusendtailsdansleChapitre8.Cestlundes
rarespointssyntaxiquesoilyaincompatibilitentreleCetleC++.

3.1.6.Lesaliasdetypes
LeC/C++disposedunmcanismedecrationdalias,oudesynonymes,destypescomplexes.Le
motclutiliserest typedef.Sasyntaxeestlasuivante:
typedefdfinitionalias;

o alias estlenomquedoitavoirlesynonymedutypeet
tableaux,lasyntaxeestparticulire:

dfinition estsadfinition.Pourles

typedeftype_tableautype[(taille)]([taille](...));
type_tableau estalorsletypedeslmentsdutableau.

Exemple39.Dfinitiondetypesimple
typedefunsignedintmot;

moteststrictementquivalentunsignedint.
Exemple310.Dfinitiondetypetableau
typedefinttab[10];

tabestlesynonymedetableaude10entiers.
Exemple311.Dfinitiondetypestructure
typedefstructclient
{
unsignedintAge;
unsignedintTaille;
}Client;

37

Chapitre3.Typesavancsetclassesdestockage
Client reprsentelastructureclient. Attentionnepasconfondrelenomdelastructure(struct
client)aveclenomdelalias(Client).
Note:Pourcomprendrelasyntaxede typedef,il suffitderaisonnerdelamaniresuivante.Si
londisposeduneexpressionqui permetdedclarerunevariableduntypedonn,alorsilsuffit
deplacerlemotcl typedef devantcetteexpressionpourfaireensortequelidentificateurdela
typedef dans
variabledevienneunidentificateurdetype.Parexemple,sionsupprimelemotcl
ladclarationdutypeClientcidessus,alorsClientdevient unevariabledont letypeest struct
client.

Unefoiscesdfinitionsdaliaseffectues,onpeutlesutilisercommenimportequeltype,puisquils
reprsententdestypes:
unsignedinti=2,j;
/*Dclaredeuxunsignedint*/
tabTableau;
/*Dclareuntableaude10entiers*/
ClientJohn;
/*Dclareunestructureclient*/
John.Age=35;/*InitialiselavariableJohn*/
John.Taille=175;
for(j=0;j <10;j=j+1)Tableau[j]=j; /*InitialiseTableau*/

3.1.7.Transtypages
Ilestparfoisutiledechangerletypedunevaleur.Considronslexemplesuivant:ladivisionde 5 par
2 renvoie 2.Eneffet, 5/2 faitappelladivisioneuclidienne.Commentfairepourobtenirlersultat
avecunnombrerel?Ilfautfaire 5./2,caralors 5. estunnombreflottant.Maisquefairequandon
setrouveavecdesvariablesentires( i et j parexemple)?Lecompilateursignaleuneerreuraprs i
danslexpression i./j !Ilfautchangerletypedelunedesdeuxvariables.Cetteoprationsappelle
letranstypage.Onlaralisesimplementenfaisantprcderlexpressiontranstyperdutypedsir
entourdeparenthses:
(type)expression

Exemple312.TranstypageenC
inti=5,j=2;
((float)i)/j

Danscetexemple, i esttranstypenflottantavantladivision.Onobtientdonc

2.5.

LetranstypageCesttoutpuissantetpeuttrerelativementdangereux.LelangageC++fournitdonc
desoprateursdetranstypagesplusspcifiques,quipermettentparexempledeconserverlaconstance
desvariableslorsdeleurtranstypage.CesoprateursserontdcritsdanslaSection10.2duchapitre
traitantdelidentificationdynamiquedestypes.

38

Chapitre3.Typesavancsetclassesdestockage

3.2.Lesclassesdestockage
LesvariablesC/C++peuventtrecresdediffrentesmanires.Ilestcourant,selonlamaniredont
ellessontcresetlamaniredontellespourronttreutilises,delesclasserendiffrentescatgories
devariables.Lesdiffrentsaspectsquepeuventprendrelesvariablesconstituentcequelonappelle
leurclassedestockage.
Laclassificationlaplussimplequelonpuissefairedesvariablesestlaclassificationlocaleglobale.
Lesvariablesglobalessontdclaresendehorsdetoutblocdinstructions,
danslazonededcla
rationglobaleduprogramme. Lesvariableslocalesenrevanchesontcreslintrieurdunbloc
dinstructions. Lesvariableslocalesetglobalesontdesduresdevie,
desportesetdesemplace
mentsenmmoirediffrents.
Laportedunevariableest lazoneduprogrammedanslaquelleelleest
accessible. Laporte
desvariablesglobalesest tout leprogramme, alorsquelaportedesvariableslocalesest
lebloc
dinstructionsdanslequelellesonttcres.
Laduredeviedunevariableestletempspendantlequelelleexiste.
Lesvariablesglobalessont
cresaudbutduprogrammeetdtruiteslafin,leurduredevieestdonccelleduprogramme.En
gnral,lesvariableslocalesontuneduredeviequivadumomentoellessontdclaresjusqu
lasortiedublocdinstructionsdanslequelellesonttdclares.Cependant,ilestpossibledefaire
ensortequelesvariableslocalessurviventlasortiedeceblocdinstructions.Dautrepart,laporte
dunevariablepeutcommenceravantsaduredeviesicettevariableestdclareaprsledbutdu
blocdinstructionsdanslequelelleestdclare.Laduredevienestdoncpasgalelaportedune
variable.
Laclassedestockagedunevariablepermetdespcifiersaduredevieetsaplaceenmmoire(sa
porteesttoujoursleblocdanslequellavariableestdclare).LeC/C++disposedunventailde
classesdestockageassezlargeetpermetdespcifierletypedevariablequelondsireutiliser:
:laclassedestockagepardfaut.Lesvariablesontpourporteleblocdinstructionsdans
lequelellesonttcres.Ellesnesontaccessiblesquedanscebloc.Leurduredevieestrestreinte
cebloc.Cemotclestfacultatif,laclassedestockage auto tantlaclassepardfaut;

auto

: cetteclassedestockagepermet
decrer desvariablesdont laporteest lebloc
dinstructionsencours, maisqui, contrairement auxvariables auto, nesont pasdtruiteslors
delasortiedecebloc. chaquefoisquelonrentredansceblocdinstructions, lesvariables
statiquesexisteront et auront pourvaleurscellesquellesavaient avant quelonquittecebloc.
Leurduredevieestdonccelleduprogramme,etellesconserventleursvaleurs.Unfichierpeut
treconsidrcommeunbloc.Ainsi,unevariablestatiquedunfichiernepeutpastreaccde
partirdunautrefichier.Celaestutileencompilationspare(voirplusloin);

static

:cetteclassedestockagepermetdecrerunevariabledontlemplacementsetrouve
dansunregistredumicroprocesseur.Ilfautbienconnatrelelangagemachinepourcorrectement
utilisercetteclassedevariable.Enpratique,cetteclasseesttrspeuutilise;

register

volatile :cetteclassedevariablesertlorsdelaprogrammationsystme.Elleindiquequuneva

riablepeuttremodifieenarrireplanparunautreprogramme(parexempleparuneinterruption,
parunthread,parunautreprocessus,parlesystmedexploitationouparunautreprocesseurdans
unemachineparallle).Celancessitedoncderechargercettevariablechaquefoisquonyfait
rfrencedansunregistreduprocesseur,etcemmesiellesetrouvedjdansundecesregistres
(cequipeutarriversionademandaucompilateurdoptimiserleprogramme);
extern :cetteclasseestutilisepoursignalerquelavariablepeuttredfiniedansunautrefichier.

Elleestutilisedanslecadredelacompilationspare(voirleChapitre6pourplusdedtails).

39

Chapitre3.Typesavancsetclassesdestockage
Ilexistegalementdesmodificateurspouvantsappliquerunevariablepourprcisersaconstance:
:cemotclestutilispourrendrelecontenudunevariablenonmodifiable.Enquelque
sorte,lavariabledevientainsiunevariableenlectureseule.Attention,unetellevariablenestpas
forcmentuneconstante:ellepeuttremodifiesoitparlintermdiairedunautreidentificateur,
soitparuneentitextrieureauprogramme(commepourlesvariables volatile).Quandcemot
clestappliquunestructure,aucundeschampsdelastructurenestaccessibleencriture.Bien
quilpuisseparatretrangedevouloirrendreconstanteunevariable,
cemotclaune
utilit.Enparticulier,ilpermetdefaireducodeplussr;

const

mutable :disponibleuniquementenC++,cemotclnesertquepourlesmembresdesstructures.

Ilpermetdepasseroutrelaconstanceventuelledunestructurepourcemembre.Ainsi,unchamp
destructuredclar mutable peuttremodifimmesilastructureestdclare const.
Pourdclareruneclassedestockageparticulire, ilsuffitdefaireprcderousuivreletypedela
variableparlundesmotscls auto, static, register,etc.Onnaledroitdenutiliserqueles
classesdestockagenoncontradictoires.Parexemple, register et extern sontincompatibles,de
mmeque register et volatile,et const et mutable.Parcontre, static et const,demme
que const et volatile,peuventtreutilisessimultanment.
Exemple313.Dclarationdunevariablelocalestatique
intappels(void)
{
staticintn=0;
returnn=n+1;
}

Cettefonctionmmoriselenombredappelsqui
nombre.Enrevanche,lafonctionsuivante:

lui ont tfaitsdanslavariable n et renvoiece

intappels(void)
{
intn=0;
returnn=n+1;
}

renverratoujours 1.Eneffet,lavariablen estcre,initialise,incrmenteetdtruitechaqueappel.


Ellenesurvitpaslafindelinstruction return.
Exemple314.Dclarationdunevariableconstante
constinti=3;
i prendlavaleur 3 etnepeutplustremodifie.

Lesvariablesglobalesquisontdfiniessanslemotcl const sonttraitesparlecompilateurcomme


desvariablesdeclassedestockage extern pardfaut.Cesvariablessontdoncaccessiblespartirde
touslesfichiersduprogramme.Enrevanche,cetterglenestpasvalidepourlesvariablesdfinies
aveclemotcl const.Cesvariablessontautomatiquementdclares static parlecompilateur,ce
quisignifiequellesnesontaccessiblesquedanslefichierdanslequelellesonttdclares.Pour
lesrendreaccessiblesauxautresfichiers,ilfautimprativementlesdclareraveclemotcl extern
avantdelesdfinir.

40

Chapitre3.Typesavancsetclassesdestockage
Exemple315.Dclarationdeconstanteexternes
inti=12;
constintj=11;

/*iestaccessibledetouslesfichiers.*/
/*Synonymede"staticconstintj=11;".*/

externconstintk;
constintk=12;

/*Dclaredabordlavariablek...*/
/*puisdonneladfinition.*/

const doiventtreinitialiseslorsdeleur
Notezquetouteslesvariablesdfiniesaveclemotcl
const,ellesdoiventdoncavoir
dfinition.Eneffet,onnepeutpasmodifierlavaleurdesvariables
unevaleurinitiale.Enfin,lesvariablesstatiquesnoninitialisesprennentlavaleurnulle.

Lesmotscls const et volatile demandentaucompilateurderaliserdesvrificationsaddition


nelleslorsdelemploidesvariablesquiontcesclassesdestockage.Eneffet,leC/C++assurequil
estinterditdemodifier(dumoinssansmagouiller)unevariabledeclassedestockage const,etil
assuregalementquetouteslesrfrencesunevariabledeclassedestockage volatile seferont
sansoptimisationsdangereuses. Cesvrificationssontbasessurletypedesvariablesmanipules.
Danslecasdestypesdebase,cesvrificationssontsimplesetdecomprhensionimmdiate.Ainsi,
leslignesdecodesuivantes:
constinti=3;
intj=2;
i=j;

/*Illgal:iestdetypeconstint.*/

gnrentuneerreurparcequonnepeutpasaffecterunevaleurdetypeintunevariabledetype
constint.
Enrevanche, pourlestypescomplexes(pointeursetrfrencesenparticulier), lesmcanismesde
vrificationssontplusfins. Nousverronsquelssontlesproblmessoulevsparlemploidesmots
cls const et volatile aveclespointeursetlesrfrencesdanslechapitretraitantdespointeurs.
Enfin, enC++uniquement, lemot cl mutable permet derendreunchampdestructure
accessibleencriture:

const

Exemple316.Utilisationdumotclmutable
structA
{
inti;
mutableintj;
};

//NonmodifiablesiAestconst.
//Toujoursmodifiable.

constAa={1,1};

//ietjvalent1.

intmain(void)
{
a.i=2;
a.j=2;
return0;
}

//ERREUR!aestdetypeconstA!
//Correct:jestmutable.

41

Chapitre3.Typesavancsetclassesdestockage

42

Chapitre4.Lespointeursetrfrences
Lespointeurssont desvariablestrsutilisesenCet enC++. Ilsdoivent treconsidrscomme
desvariables,ilnyariendesorcierderrirelespointeurs.Cependant,lespointeursontundomaine
dapplicationtrsvaste.
Lesrfrencessontdesidentificateurssynonymesdautresidentificateurs,quipermettentdemanipu
lercertainesnotionsintroduitesaveclespointeursplussouplement.EllesnexistentquenC++.

4.1.Notiondadresse
Toutobjetmanipulparlordinateureststockdanssammoire.Onpeutconsidrerquecettem
moireest constituedunesriedecases, casesdanslesquellessont stockeslesvaleursdes
variablesoulesinstructionsduprogramme.Pourpouvoiraccderunobjet(lavaleurdunevariable
oulesinstructionsexcuterparexemple),cestdireaucontenudelacasemmoiredanslaquelle
cet objet est enregistr, il faut connatrelenumrodecettecase. Autrement dit, il faut connatre
lemplacementenmmoiredelobjetmanipuler.Cetemplacementestappelladressedelacase
mmoire,etparextension,ladressedelavariableouladressedelafonctionstockedanscettecase
etcellesquilasuivent.
Toutecasemmoireauneadresseunique. Lorsquonutiliseunevariableouunefonction, lecom
pilateurmanipuleladressedecettedernirepouryaccder.
Cestluiquiconnatcetteadresse, le
programmeurnapassensoucier.

4.2.Notiondepointeur
Uneadresseestunevaleur.Onpeutdoncstockercettevaleurdansunevariable.Lespointeurssont
justementdesvariablesquicontiennentladressedautresobjets,parexempleladresseduneautre
variable.Onditquelepointeurpointesurlavariablepointe.Ici,pointersignifiefairerfrence.
Lesadressessontgnralementdesvaleursconstantes,carengnralunobjetnesedplacepasen
mmoire.Toutefois,lavaleurdunpointeurpeutchanger.Celanesignifiepasquelavariablepointe
estdplaceenmmoire,maispluttquelepointeurpointesurautrechose.
Afindesavoircequiestpointparunpointeur,lespointeursdisposentduntype.Cetypeestconstruit
partirdutypedelobjetpoint.Celapermetaucompilateurdevrifierquelesmanipulationsrali
sesenmmoireparlintermdiairedupointeursontvalides.Letypedespointeurselitpointeurde
...,olespointsdesuspensionreprsententlenomdutypedelobjetpoint.
Lespointeurssedclarentendonnantletypedelobjetquilsdevrontpointer,suivideleuridentifi
cateurprcddunetoile:
int*pi;

//piestunpointeurdentier.

Note:Siplusieurspointeursdoiventtredclars,ltoiledoittrerpte:
int*pi1,*pi2,j,*pi3;

Ici, pi1, pi2 et pi3 sontdespointeursdentierset j estunentier.

43

Chapitre4.Lespointeursetrfrences
Figure41.Notiondepointeuretdadresse

Ilestpossibledefaireunpointeursurunestructuredansunestructureenindiquantlenomdela
structurecommetypedupointeur:
typedefstructnom
{
structnom*pointeur;
...
}MaStructure;

/*Pointeursurunestructure"nom".*/

Cetypedeconstructionpermet decrerdeslistesdestructures, danslesquelleschaquestructure


contientladressedelastructuresuivantedanslaliste.Nousverronsplusloinunexempledutilisation
decegenredestructure.
Ilestgalementpossibledecrerdespointeurssurdesfonctions,etdutilisercespointeurspourpara
mtrerunalgorithme,dontlecomportementdpendradesfonctionsainsipointes.Nousdtaillerons
plusloincetypedutilisationdespointeurs.

4.3.Drfrencement,indirection
Unpointeurneserviraitstrictementriensilnyavaitpasdepossibilitdaccderladressedune
variableoudunefonction(onnepourraitalorspaslinitialiser)ousilnyavaitpasmoyendaccder
lobjetrfrencparlepointeur(lavariablepointenepourraitpastremanipuleoulafonction
pointenepourraitpastreappele).
Cesdeuxoprationssontrespectivementappelesindirectionetdrfrencement.Ilexistedeuxop
rateurspermettantdercuprerladressedunobjetetdaccderlobjetpoint.Cesoprateurssont
respectivement & et *.
Ilesttrsimportantdesassurerquelespointeursquelonmanipulesonttousinitialiss(cest
direcontiennentladressedunobjetvalide,etpasnimportequoi).Eneffet,accderunpointeur

44

Chapitre4.Lespointeursetrfrences
noninitialisrevientlireou,plusgraveencore,criredanslammoireunendroitcompltement
alatoire(selonlavaleurinitialedupointeurlorsdesacration).Engnral,oninitialiselespointeurs
dsleurcration,ou,silsdoiventtreutilissultrieurement,onlesinitialiseaveclepointeurnul.
Celapermettradefaireultrieurementdestestssurlavaliditdupointeurouaumoinsdedtecter
leserreurs.Eneffet,lutilisationdunpointeurinitialisaveclepointeurnulgnresouventunefaute
deprotectionduprogramme,quetoutbondbogueurestcapablededtecter.Lepointeurnulsenote
NULL.
Note: NULL estunemacrodfiniedanslefichierdentte stdlib.h .EnC,ellereprsentela
valeurduneadresseinvalide.Malheureusement,cettevaleurpeutnepastregaleladresse
0 (certainscompilateursutilisentlavaleur1 pour NULL parexemple).Cestpourcelaquecette
macroatdfinie,afindereprsenter,selonlecompilateur,labonnevaleur.VoirleChapitre5
pourplusdedtailssurlesmacrosetsurlesfichiersdentte.
LanormeduC++fixelavaleurnulledespointeurs 0.Parconsquent,lescompilateursC/C++
quidfinissent NULL commetantgal 1 posentunproblmedeportabilitcertain,puisqueun
programmeCqui utilise NULL nestplusvalideenC++.Parailleurs,unmorceaudeprogramme
C++compilableenCquiutiliseraitlavaleur 0 neseraitpascorrectenC.
Il fautdoncfaireunchoix:soitutiliser NULL enCet 0 enC++,soitutiliser NULL partout,quitte
redfinirlamacro NULL pourlesprogrammesC++(solutionquimesemblepluspratique).

Exemple41.Dclarationdepointeurs
inti=0;
int*pi;
pi=&i;
*pi=*pi+1;

/*Dclareunevariableentire.*/
/*Dclareunpointeursurunentier.*/
/*Initialiselepointeuravecladressedecette
variable.*/
/*Effectueuncalculsurlavariablepointeparpi,
cestdiresuriluimme,puisquepicontient
ladressedei.*/
/*cestade,inevautplus0,mais1.*/

Ilestprsentfaciledecomprendrepourquoiilfautrpterltoiledansladclarationdeplusieurs
pointeurs:
int*p1,*p2,*p3;

signifiesyntaxiquement: p1, p2 et p3 sontdespointeursdentiers,maisaussi *p1, *p2 et *p3 sont


desentiers.
Silonavaitcrit:
int*p1,p2,p3;

seul p1 seraitunpointeurdentier. p2 et p3 seraientdesentiers.


Laccsauxchampsdunestructureparlepointeursurcettestructureseferaavecloprateur
quiremplace (*)..

>,

Exemple42.Utilisationdepointeursdestructures
structClient
{
intAge;

45

Chapitre4.Lespointeursetrfrences
};
Clientstructure1;
Client*pstr=&structure1;
pstr>Age=35;
/*Onauraitpucrire(*pstr).Age=35;*/

4.4.Notionderfrence
Enplusdespointeurs, leC++permetdecrerdesrfrences. Lesrfrencessontdessynonymes
didentificateurs.Ellespermettentdemanipulerunevariablesousunautrenomqueceluisouslaquelle
cettedernireatdclare.
Note:LesrfrencesnexistentquenC++.LeCnepermetpasdecrerdesrfrences.

ref de
Parexemple,si id estlenomdunevariable,ilestpossibledecrerunerfrence
cettevariable.Lesdeuxidentificateurs id et ref reprsententalorslammevariable,etcellecipeut
treaccdeetmodifielaidedecesdeuxidentificateursindistinctement.

Touterfrencedoitserfrerunidentificateur:ilestdoncimpossiblededclarerunerfrence
sanslinitialiser. Deplus, ladclarationdunerfrencenecrepasunnouvelobjetcommecest
lecaspourladclarationdunevariableparexemple. Eneffet, lesrfrencesserapportent des
identificateursdjexistants.
Lasyntaxedeladclarationdunerfrenceestlasuivante:
type&rfrence=identificateur;

Aprscettedclaration, rfrencepeuttreutilispartoutoidentificateurpeutltre. Cesontdes


synonymes.
Exemple43.Dclarationderfrences
inti=0;
int&ri=i;
ri=ri+i;

//Rfrencesurlavariablei.
//Doublelavaleurdei(etderi).

Ilestpossibledefairedesrfrencessurdesvaleursnumriques.Danscecas,lesrfrencesdoivent
tredclarescommetantconstantes,puisquunevaleurestuneconstante:
constint&ri=3;
int&error=4;

//Rfrencesur3.
//Erreur!Larfrencenestpasconstante.

4.5.Lienentrelespointeursetlesrfrences
Lesrfrencesetlespointeurssonttroitementlis.Eneffet,unevariableetsesdiffrentesrfrences
ontlammeadresse,puisquellespermettentdaccderunmmeobjet.Utiliserunerfrencepour

46

Chapitre4.Lespointeursetrfrences
manipulerunobjetrevientdoncexactementaummequedemanipulerunpointeurconstantconte
nantladressedecetobjet.Lesrfrencespermettentsimplementdobtenirlemmersultatqueles
pointeurs,maisavecuneplusgrandefacilitdcriture.
Cettesimilitudeentrelespointeursetlesrfrencesseretrouveauniveausyntaxique.Parexemple,
considronslemorceaudecodesuivant:
inti=0;
int*pi=&i;
*pi=*pi+1;

//Manipulationdeiviapi.

etfaisonspasserloprateur&deladeuximelignegauchedeloprateurdaffectation:
inti=0;
int&*pi=i;

//Celagnreuneerreurdesyntaxemaisnous
//lignoronspourlesbesoinsdelexplication.

*pi=*pi+1;

Maintenant,comparonsaveclemorceaudecodequivalentsuivant:
inti=0;
int&ri=i;
ri=ri+1;

//Manipulationdeiviari.

Nousconstatonsquelarfrence ri peuttreidentifieaveclexpression *pi,quireprsentebelet


bienlavariable i.Ainsi,larfrence ri encapsulelamanipulationdeladressedelavariable i et
sutilisecommelexpression *pi.Celapermetdecomprendreloriginedelasyntaxededclaration
desrfrences.Ladiffrencesetrouveicidanslefaitquelesrfrencesdoiventtreinitialisesdune
part,etquelonnapaseffectuerledrfrencementdautrepart.Lesrfrencessontdoncbeaucoup
plusfacilesmanipulerquelespointeurs,etpermettentdefaireducodebeaucoupplussr.

4.6.Passagedeparamtresparvariableouparvaleur
Ilyadeuxmthodespourpasserdesvariablesenparamtredansunefonction:lepassageparvaleur
etlepassageparvariable.Cesmthodessontdcritescidessous.

4.6.1.Passageparvaleur
Lavaleurdelexpressionpasseenparamtreestcopiedansunevariablelocale.Cestcettevariable
quiestutilisepourfairelescalculsdanslafonctionappele.
Silexpressionpasseenparamtreestunevariable,soncontenuestcopidanslavariablelocale.
Aucunemodificationdelavariablelocaledanslafonctionappelenemodifielavariablepasseen
paramtre,parcequecesmodificationsnesappliquentquunecopiedecettedernire.
LeCnepermetdefairequedespassagesparvaleur.

47

Chapitre4.Lespointeursetrfrences
Exemple44.Passagedeparamtreparvaleur
voidtest(intj)

/*jestlacopiedelavaleurpasseen
paramtre*/

{
j=3;

/*Modifiej,maispaslavariablefournie
parlappelant.*/

return;
}
intmain(void)
{
inti=2;
test(i);
test(2);
return0;

/*Lecontenudeiestcopidansj.
inestpasmodifi.Ilvauttoujours2.*/
/*Lavaleur2estcopiedansj.*/

4.6.2.Passageparvariable
Ladeuximetechniqueconsistepassernonpluslavaleurdesvariablescommeparamtre,mais
passerlesvariablesellesmmes.Ilnyadoncplusdecopie,plusdevariablelocale.Toutemodifica
tionduparamtredanslafonctionappeleentranelamodificationdelavariablepasseenparamtre.
LeCnepermetpasdefairecetypedepassagedeparamtres(leC++lepermetenrevanche).
Exemple45.PassagedeparamtreparvariableenPascal
Vari:integer;
Proceduretest(Varj:integer)
Begin
{Lavariablejeststrictementgale
lavariablepasseenparamtre.}
j:=2;
{Ici,cettevariableestmodifie.}
End;
Begin
i:=3;
{Initialisei3}
test(i);{Appellelafonction.Lavariableiestpasseen
paramtres,passavaleur.Elleestmodifiepar
lafonctiontest.}
{Ici,ivaut2.}
End.

Puisquelafonctionattendunevariableenparamtre,onnepeutplusappeler test avecunevaleur


(test(3) estmaintenantinterdit,car 3 nestpasunevariable:onnepeutpaslemodifier).

48

Chapitre4.Lespointeursetrfrences

4.6.3.Avantagesetinconvnientsdesdeuxmthodes
Lespassagesparvariablessontplusrapidesetplusconomesenmmoirequelespassagesparvaleur,
puisquelestapesdelacrationdelavariablelocaleetlacopiedelavaleurnesontpasfaites.
Il
fautdoncviterlespassagesparvaleurdanslescasdappelsrcursifsdefonctionoudefonctions
travaillantavecdesgrandesstructuresdedonnes(matricesparexemple).
Lespassagesparvaleurspermettentdviterdedtruireparmgardelesvariablespassesenpara
mtre. Silonveutseprvenirdeladestructionaccidentelledesparamtrespasssparvariable, il
faututiliserlemotcl const.Lecompilateurinterdiraalorstoutemodificationdelavariabledansla
fonctionappele,cequipeutparfoisobligercettefonctionraliserdescopiesdetravailenlocal.

4.6.4.CommentpasserlesparamtresparvariableenC?
Il nyaquunesolution:
pointeurs.

passerladressedelavariable. Celaconstituedoncuneapplicationdes

VoicicommentlExemple45seraitprogrammenC:
Exemple46.PassagedeparamtreparvariableenC
voidtest(int*pj)
{
*pj=2;
return;
}

/*testattendladressedunentier...*/
/*...pourlemodifier.*/

intmain(void)
{
inti=3;
test(&i);
/*Onpasseladressedeienparamtre.*/
/*Ici,ivaut2.*/
return0;
}

prsent,ilestfaciledecomprendrelasignificationde&danslappelde
entrersontpassesparvariable.

scanf :lesvariables

4.6.5.Passagedeparamtresparrfrence
LasolutionduCestexactementlammequecelleduPascaldupointdevuesmantique.Enfait,
lePascalprocdeexactementdelammemanireeninterne,maislamanipulationdespointeursest
masqueparlelangage.Cependant,plusieursproblmesseposentauniveausyntaxique:

lasyntaxeestlourdedanslafonction,causedelemploideloprateur

* devantlesparamtres;

lasyntaxeestdangereuselorsdelappeldelafonction,puisquilfautsystmatiquementpenser
utiliserloprateur & devantlesparamtres.Unoublidevantunevariabledetypeentieretlavaleur
delentierestutiliselaplacedesonadressedanslafonctionappele(plantageassur,essayez
avec scanf).

49

Chapitre4.Lespointeursetrfrences
LeC++permetdersoudretouscesproblmeslaidedesrfrences.Aulieudepasserlesadresses
desvariables,ilsuffitdepasserlesvariablesellesmmesenutilisantdesparamtressouslaformede
rfrences.Lasyntaxedesparamtresdevientalors:
type&identificateur[,type&identificateur[...]]

Exemple47.PassagedeparamtreparrfrenceenC++
voidtest(int&i)
//iestunerfrenceduparamtreconstant.
{
i=2;
//Modifieleparamtrepassenrfrence.
return;
}
intmain(void)
{
inti=3;
test(i);
//Aprslappeldetest,ivaut2.
//Loprateur&nestpasncessairepourappeler
//test.
return0;
}

Ilestrecommand,pourdesraisonsdeperformances,depasserparrfrencetouslesparamtresdont
lacopiepeutprendrebeaucoupdetemps(enpratique,seulslestypesdebasedulangagepourronttre
passsparvaleur).Bienentendu,ilfaututiliserdesrfrencesconstantesaumaximumafindviter
lesmodificationsaccidentellesdesvariablesdelafonctionappelantedanslafonctionappele.
En
revanche,lesparamtresderetourdesfonctionsnedevrontpastredclarscommedesrfrences
constantes,caronnepourraitpaslescriresictaitlecas.
Exemple48.Passagedeparamtresconstantparrfrence
typedefstruct
{
...
}structure;
voidma_fonction(conststructure&s)
{
...
return;
}

Danscetexemple, s estunerfrencesurunestructureconstante.Lecodesetrouvantlintrieur
delafonctionnepeutdoncpasutiliserlarfrence s pourmodifierlastructure(onnoteracependant
quecestlafonctionellemmequisinterditlcrituredanslavariable s. const estdoncunmot
clcoopratif.Ilnestpaspossibleunprogrammeurdempchersescollguesdcriredansses
variablesaveclemotcl const.NousverronsdansleChapitre8queleC++permetdepallierce
problmegrceunetechniqueappelelencapsulation.).
Unautreavantagedesrfrencesconstantespourlespassagesparvariablesestquesileparamtre
nestpasunevariableou,silnestpasdubontype,unevariablelocaledutypeduparamtreestcre
etinitialiseaveclavaleurduparamtretranstyp.

50

Chapitre4.Lespointeursetrfrences
Exemple49.Crationdunobjettemporairelorsdunpassageparrfrence
voidtest(constint&i)
{
...
//Utilisationdelavariablei
//danslafonctiontest.Lavariable
//iestcresincessaire.
return;
}
intmain(void)
{
test(3);
//Appeldetestavecuneconstante.
return0;
}

Aucoursdecetappel,unevariablelocaleestcre(lavariable
affecte.

i delafonction test),et 3 luiest

4.7.Rfrencesetpointeursconstantsetvolatiles
Lutilisationdesmotscls const et volatile aveclespointeursetlesrfrencesestunpeuplus
compliquequaveclestypessimples.Eneffet,ilestpossiblededclarerdespointeurssurdesva
riables, despointeursconstantssurdesvariables, despointeurssurdesvariablesconstantesetdes
pointeursconstantssurdesvariablesconstantes(bienentendu,ilenestdemmeaveclesrfrences).
Lapositiondesmotscls const et volatile danslesdclarationsdestypescomplexesestdonc
extrmementimportante.Engnral,lesmotscls const et volatile caractrisentcequilespr
cdedansladclaration,silonadoptecommergledetoujourslesplaceraprslestypesdebase.
Parexemple,lexpressionsuivante:
constint*pi;

peuttrercritedelamaniresuivante:
intconst*pi;

puisquelemotcl const estinterchangeableavecletypeleplussimpledansunedclaration.


Ce
motclcaractrisedoncletypeint,et pi estunpointeursurunentierconstant.Enrevanche,dans
lexemplesuivant:
intj;
int*constpi=&j;
pi estdclarcommetantconstant,etdetypepointeurdentier.Ilsagitdoncdunpointeurconstant
surunentiernonconstant,queloninitialisepourrfrencerlavariable j.
Note:LesdclarationsC++peuvent devenirtrscompliqueset difficileslire. Il existeune
astucequipermetdelesinterprterfacilement.Lorsdelanalysedeladclarationdunidentifica
teur X,ilfauttoujourscommencerparunephrasedutype Xestun... .Pourtrouverlasuite
delaphrase,ilsuffitdelireladclarationenpartantdelidentificateuretdesuivrelordreimpos

51

Chapitre4.Lespointeursetrfrences
parlesprioritsdesoprateurs. Cet ordrepeut tremodifiparlaprsencedeparenthses.
LannexeBdonnelesprioritsdetouslesoprateursduC++.
Ainsi,danslexemplesuivant:
constint*pi[12];
void(*pf)(int*constpi);

lapremiredclarationselit delamaniresuivante: pi (pi)est untableau( [])de12( 12)


pointeurs( *)dentiers( int)constants( const).Ladeuximedclarationselit:pf(pf)estun
pointeur( *)defonction( ())depi (pi),qui estluimmeuneconstante( const)detypepointeur
(*)dentier( int).Cettefonctionnerenvoierien( void).

LeCetleC++nautorisentquelescrituresquiconserventouaugmententlespropritsdeconstance
etdevolatilit.Parexemple,lecodesuivantestcorrect:
char*pc;
constchar*cpc;
cpc=pc;

/*Lepassagedepccpcaugmentelaconstance.*/

pc,
parcequellesignifiequesilonpeutcriredansunevariableparlintermdiairedupointeur
cpc
pc
onpeutsinterdiredelefaireenutilisant
laplacede
.Enrevanche,silonnapasledroit
dcriredansunevariable,onnepeutenaucuncasseledonner.

Cependant, lesrglesdulangagerelativeslamodificationdesvariablespeuvent
tranges.Parexemple,lelangageinterditunecrituretellequecelleci:

parfoisparatre

char*pc;
constchar**ppc;
ppc=&pc;

/*Interdit!*/

Pourtant, cet exempleressemblebeaucouplexempleprcdent.


Onpourrait penserquelefait
daffecterunpointeurdepointeurdevariableunpointeurdepointeurdevariableconstanterevient
sinterdiredcriredansunevariablequonaledroitdemodifier. Maisenralit, cettecriture
vacontrelesrglesdeconstances,parcequellepermettraitdemodifierunevariableconstante.Pour
senconvaincre,ilfautregarderlexemplesuivant:
constcharc=a;
char*pc;
constchar**ppc=&pc;
*ppc=&c;
*pc=b;

/*Lavariableconstante.*/
/*Pointeurparlintermdiaireduquel
nousallonsmodifierc.*/
/*Interdit,maissupposonsquecenele
soitpas.*/
/*Parfaitementlgal.*/
/*Modifielavariablec.*/

Quesestilpass?Nousavons,parlintermdiairede ppc,affectladressedelaconstantec aupoin


teur pc.Malheureusement, pc nestpasunpointeurdeconstante,etcelanousapermisdemodifier
laconstante c.

52

Chapitre4.Lespointeursetrfrences
Afindegrercorrectementcettesituation(etlessituationspluscomplexesquiutilisentdestriples
pointeursouencoreplusdindirection),leCetleC++interdisentlaffectationdetoutpointeurdont
lespropritsdeconstanceetdevolatilitsontmoindresquecellesdupointeurcible.Largleexacte
estlasuivante:
1.Onnote cv lesdiffrentesqualificationsdeconstanceetdevolatilitpossibles(savoir: const
volatile, const, volatile ouaucuneclassedestockage).
2.Si lepointeur sourceest unpointeur cvs,0 depointeur cvs,1 depointeur ... depointeur
cvs,n1 detype Tscvs,n,etquelepointeurdestinationestunpointeur cvd,0 depointeur
cvd,1 depointeur...depointeur cvd,n1 detype Tdcvs,n,alorslaffectationdelasource
ladestinationnestlgalequesi:

lestypessource Ts etdestination Td sontcompatibles;

ilexisteunnombreentierstrictementpositif N telque,quelquesoit j suprieurougal N,


onait:

si const apparatdans cvs,j,alors const apparatdans cvd,j ;

si volatile apparatdans cvs,j,alors volatile apparatdans cvd,j ;

ettelque,quelquesoit 0<k<N, const apparaissedans cvd,k.

Cesrglessontsuffisammentcompliquespournepastreapprises.Lescompilateurssechargeront
designalerleserreurssilyenaenpratique.Parexemple:
constcharc=a;
constchar*pc;
constchar**ppc=&pc;
*ppc=&c;
*pc=b;

/*Lgalprsent.*/
/*Illgal(pcachangdetype).*/

Laffectationdedoublepointeurestprsentlgale,parcequelepointeursourceachangdetype
(onnepeutcependanttoujourspasmodifierlecaractre c).
Ilexisteuneexceptionnotablecesrgles:linitialisationdeschanesdecaractres.Leschanesde
caractrestellesque:
"Bonjourtoutlemonde!"

sont deschanesdecaractresconstantes. Parconsquent, onnepeut thoriquement affecterleur


adressequdespointeursdecaractresconstants:
constchar*pc="Coucou!";/*Codecorrect.*/

Cependant,ilatoujourstdusagederaliserlinitialisationdeschanesdecaractresdelamanire
suivante:
char*pc="Coucou!";

/*Thoriquementillgal,maistolr
parcompatibilitavecleC.*/

53

Chapitre4.Lespointeursetrfrences

Parcompatibilit, lelangagefournit doncuneconversionimpliciteentre constchar* et


char* .Cettefacilitnedoitpaspourautantvousincitertransgresserlesrglesdeconstance:
utilisezlespointeurssurleschanesdecaractresconstantsautantquevouslepourrez(quittera
liserquelquescopiesdechaneslorsquunpointeurdecaractresimpledoittreutilis).Surcertains
systmes,lcrituredansunechanedecaractresconstantepeutprovoquerunplantageimmdiatdu
programme.

4.8.Arithmtiquedespointeurs
Ilestpossibledeffectuerdesoprationsarithmtiquessurlespointeurs.
Lesseulesoprationsvalidessontlesoprationsexternes(additionetsoustractiondesentiers)etla
soustractiondepointeurs.Ellessontdfiniescommesuit(lasoustractiondunentierestconsidre
commeladditiondunentierngatif):
p+i=adressecontenuedansp+i*taille(lmentpointparp)

et:
p2p1=(adressecontenuedansp2adressecontenuedansp1)/
taille(lmentspointsparp1etp2)

Si p estunpointeurdentier, p+1 estdonclepointeursurlentierquisuitimmdiatementceluipoint


par p. Onretiendrasurtout quelentierquonadditionneaupointeurest multipliparlataillede
llmentpointpourobtenirlanouvelleadresse.
Letypedursultatdelasoustractiondedeuxpointeursesttrsdpendantdelamachinecibleetdu
modlemmoireduprogramme.Engnral,onnepourrajamaissupposerquelasoustractiondedeux
pointeursestunentier(queleschevronnsduCmepardonnent,maiscestuneerreurtrsgrave).En
effet,cetypepeuttreinsuffisantpourstockerdesadresses(unemachinepeutavoirdesadressessur
64bitsetdesdonnessur32bits).Pourrsoudreceproblme,lefichierdentte stdlib.h contient
ladfinitiondutypeutiliserpourladiffrencededeuxpointeurs.Cetypeestnommptrdiff_t.
Exemple410.Arithmtiquedespointeurs
inti,j;
ptrdiff_tdelta=&i&j;
interror=&i&j;

/*Correct*/
/*Peutmarcher,maisparchance.*/

Ilestpossibledeconnatrelatailledunlmentencaractresenutilisantloprateursizeof.Ilala
syntaxedunefonction:
sizeof(type|expression)

Ilattendsoituntype,soituneexpression.Lavaleurretourneestsoitlatailledutypeencaractres,
soitcelledutypedelexpression.Danslecasdestableaux,ilrenvoielatailletotaledutableau.Sison
argumentestuneexpression,cellecinestpasvalue(doncsiilcontientunappelunefonction,
cellecinestpasappele).Parexemple:

54

Chapitre4.Lespointeursetrfrences
sizeof(int)

renvoielatailledunentierencaractres,et:
sizeof(2+3)

renvoielammetaille,car 2+3 estdetypeentier. 2+3 nestpascalcul.


Note:Loprateur sizeof renvoielatailledestypesentenantcomptedeleuralignement.Cela
signifieparexemplequemmesi uncompilateurespaceleslmentsduntableauafindeles
alignersurdesmotsmmoiredelamachine, latailledeslmentsdutableauseracelledes
objetsdemmetypequi nesetrouventpasdanscetableau(ilsdevrontdonctrealignseux
aussi).Onadonctoujourslgalitsuivante:
sizeof(tableau)=sizeof(lment)*nombredlments

4.9.Utilisationdespointeursaveclestableaux
Lestableauxsonttroitementlisauxpointeursparceque,demanireinterne,laccsauxlments
destableauxsefaitparmanipulationdeleuradressedebase, delatailledeslmentsetdeleurs
indices.Enfait,ladressedunimelmentduntableauestcalculeaveclaformule:
Adresse_n=Adresse_Base+n*taille(lment)

o taille(lment) reprsentelatailledechaquelmentdutableauet Adresse_Base ladresse


debasedutableau.Cetteadressedebaseestladressedudbutdutableau,cestdonclafoisladresse
dutableauetladressedesonpremierlment.
Celienapparatauniveaudulangagedanslesconversionsimplicitesdetableauxenpointeurs,etdans
lepassagedestableauxenparamtredesfonctions.

4.9.1.Conversionsdestableauxenpointeurs
Afindepouvoirutiliserlarithmtiquedespointeurspourmanipulerleslmentsdestableaux,leC++
effectuelesconversionsimplicitessuivanteslorsquencessaire:

tableauverspointeurdlment;

pointeurdlmentverstableau.

Celapermetdeconsidrerlesexpressionssuivantescommequivalentes:
identificateur[n]

et:
*(identificateur+n)

55

Chapitre4.Lespointeursetrfrences
si identificateur estsoitunidentificateurdetableau,soitceluidunpointeur.
Exemple411.Accsauxlmentsduntableauparpointeurs
inttableau[100];
int*pi=tableau;
tableau[3]=5;
/*Le4melmentestinitialis5*/
*(tableau+2)=4;/*Le3melmentestinitialis4*/
pi[5]=1;
/*Le6melmentestinitialis1*/
Note:LelangageC++imposequeladressesuivantledernierlmentduntableaudoittoujours
trevalide.Celanesignifieabsolumentpasquelazonemmoirerfrenceparcetteadresse
estvalide,bienaucontraire,maispluttquecetteadresseestvalide.Ilestdoncgarantitquecette
adresseneserapaslepointeurNULLparexemple,nitouteautrevaleurspcialequunpointeur
nepeutpasstocker.Il seradoncpossibledefairedescalculsdarithmtiquedespointeursavec
cetteadresse,mmesiellenedevrajamaistredrfrence,souspeinedevoirleprogramme
planter.
Onprendragardecertainessubtilits.Lesconversionsimplicitessontunefacilitintroduitepar
lecompilateur, maisenralit, lestableauxnesont pasdespointeurs, cesont desvariables
commelesautres, ceci prs: leurtypeest convertibleenpointeursurletypedeleursl
ments.Il enrsulteparfoisquelquesambigutslorsquonmanipulelesadressesdestableaux.
Enparticulier,onalgalitsuivante:
&tableau==tableau

enraisondufaitqueladressedutableauestlammequecelledesonpremierlment.Il faut
biencomprendrequedanscetteexpression,uneconversionalieu.Cettegalitnestdoncpas
exacteenthorie.Eneffet,sictaitlecas,onpourraitcrire:
*&tableau==tableau

puisquelesoprateurs * et & sontconjugus,do:


tableau==*&tableau=*(&tableau)==*(tableau)==t[0]

cequiestfaux(letypedupremierlmentnestengnralpasconvertibleentypepointeur.).

4.9.2.Paramtresdefonctiondetypetableau
Laconsquencelaplusimportantedelaconversiontableauverspointeursetrouvedanslepassagepar
variabledestableauxdansunefonction.Lorsdupassageduntableauenparamtredunefonction,
laconversionimplicitealieu,lestableauxsontdonctoujourspasssparvariable,jamaisparvaleur.
Ilestdoncfauxdutiliserdespointeurspourlespasserenparamtre,carleparamtreauraitletype
pointeurdetableau. Onnemodifierait pasletableau, maisbel et bienlepointeurdutableau. Le
programmeauraitdoncdeforteschancesdeplanter.
Parailleurs,certainescaractristiquesdestableauxpeuventtreutilisespourlespasserenparamtre
danslesfonctions.
Ilestautorisdenepasspcifierlatailledeladerniredimensiondesparamtresdetypetableau
danslesdclarationsetlesdfinitionsdefonctions.Eneffet,labornesuprieuredestableauxnapas

56

Chapitre4.Lespointeursetrfrences
besoindtreprcisepourmanipulerleurslments(onpeutmalgrtoutladonnersicelasemble
ncessaire).
Cependant,pourlesdimensionsdeuxetsuivantes,lestaillesdespremiresdimensionsrestentnces
saires.Siellesntaientpasdonnesexplicitement,lecompilateurnepourraitpasconnatrelerapport
desdimensions.Parexemple,lasyntaxe:
inttableau[][];

utilisepourrfrenceruntableaude12entiersnepermettraitpasdefaireladiffrenceentreles
tableauxdedeuxlignesetdesixcolonnesetlestableauxdetroislignesetdequatrecolonnes(etleurs
transpossrespectifs).Unerfrencetelleque:
tableau[1][3]

nereprsenteraitrien. Selonletypedetableau, llmentrfrencseraitlequatrimelmentde


ladeuximeligne(desixlments), soit lediximelment, oubienlequatrimelment dela
deuximeligne(dequatrelments),soitlehuitimelmentdutableau.Enprcisanttouslesindices
saufun,ilestpossibledeconnatrelatailledutableaupourcetindicepartirdelatailleglobaledu
tableau,enladivisantparlestaillessurlesautresdimensions(2=12/6ou3=12/4parexemple).
Leprogrammedexemplesuivantillustrelepassagedestableauxenparamtre:
Exemple412.Passagedetableauenparamtre
inttab[10][20];
voidtest(intt[][20])
{
/*Utilisationdet[i][j]...*/
return;
}
intmain(void)
{
test(tab);
return0;
}

/*Passagedutableauenparamtre.*/

4.10.Leschanesdecaractres:pointeursettableaux
lafois!
OnavudanslepremierchapitrequeleschanesdecaractresnexistaientpasenC/C++.Cesonten
ralitdestableauxdecaractresdontlederniercaractreestlecaractrenul.
Celaaplusieursconsquences.Lapremire,cestqueleschanesdecaractressontaussidespoin
teurssurdescaractres,cequisetraduitdanslasyntaxedeladclarationdunechanedecaractres
constante:
constchar*identificateur="chane";

57

Chapitre4.Lespointeursetrfrences
identificateur est dclarici commetant unpointeurdecaractre,
ladressedelachanedecaractresconstante "chane".

puisil est initialisavec

Ladeuximeest lefait quonnepeut pasfaire, commeenPascal, desaffectationsdechanesde


caractres,nidescomparaisons.Parexemple,si nom1 et nom2 sontdeschanesdecaractres,
lopration:
nom1=nom2;

nestpaslaffectationducontenudenom2 nom1.Cestuneaffectationdepointeur:lepointeurnom1
estgalaupointeur nom2 etpointentsurlammechane!Unemodificationdelachanepointepar
nom1 entranedonclamodificationdelachanepointepar nom2...
Demme,letest nom1==nom2 estuntestentrepointeurs,pasentrechanesdecaractres.Mmesi
deuxchanessontgales,letestserafauxsiellesnesontpasaummeemplacementmmoire.
IlexistedanslabibliothqueCdenombreusesfonctionspermettantdemanipulerleschanesdeca
ractres.Parexemple,lacopiedunechanedecaractresdansuneautreseferaaveclesfonctions
strcpy et strncpy,lacomparaisondedeuxchanesdecaractrespourratreraliselaidedes
fonctions strcmp et strncmp,etladterminationdelalongueurdunechanedecaractreslaide
delafonction strlen. Jevousinviteconsulterladocumentationdevotreenvironnementded
veloppementoulabibliographiepourdcouvrirtouteslesfonctionsdemanipulationdeschanesde
caractres.Nousenverronsunexempledutilisationdanslasectionsuivante.

4.11.Allocationdynamiquedemmoire
Lespointeurssontsurtoututilisspourcrerunnombrequelconquedevariables,oudesvariablesde
taillequelconque,encoursdexcutionduprogramme.
Entempsnormal,lesvariablessontcresautomatiquementlorsdeleurdfinition.Celaestfaisable
parcequelesvariablescrerainsiqueleurstaillessontconnuesaumomentdelacompilation(cest
lebutdesdclarationsquedindiquerlastructureetlatailledesobjets,etplusgnralementdedonner
lesinformationsncessairesleurutilisation).Parexemple,unelignecomme:
inttableau[10000];

signaleaucompilateurquunevariabletableau de10000entiersdoittrecre.Leprogrammesen
chargeradoncautomatiquementlorsdelexcution.
Maissupposonsqueleprogrammegreunelistedepersonnes.
Onnepeut passavoirlavance
combiendepersonnesserontentres,lecompilateurnepeutdoncpasfairelarservationdelespace
mmoireautomatiquement.Cestauprogrammeurdelefaire.Cetterservationdemmoire(appele
encoreallocation)doittrefaitependantlexcutionduprogramme.Ladiffrenceavecladclaration
detableauprcdente,cestquelenombredepersonnesetdonclaquantitdemmoireallouer,est
variable.Ilfautdoncfairecequonappelleuneallocationdynamiquedemmoire.

4.11.1.AllocationdynamiquedemmoireenC
Il existe deuxprincipales fonctions Cpermettant de demander de la mmoire ausystme
dexploitationetdelaluirestituer.Ellesutilisenttouteslesdeuxlespointeurs,parcequunevariable
allouedynamiquementnapasdidentificateurtantdonnquellentaitaprioripasconnuela

58

Chapitre4.Lespointeursetrfrences
compilation,etnadoncpasputredclare.LespointeursutilissparcesfonctionsCnontpasde
type.Onlesrfrencedoncavecdespointeursnontyps.Leursyntaxeestlasuivante:
malloc(taille)
free(pointeur)

malloc (abrviationdeMemoryALLOCation)allouedelammoire.Elleattendcommepara

mtrelatailledelazonedemmoirealloueretrenvoieunpointeurnontyp(void*).
free (pourFREEmemory)librelammoirealloue.Elleattendcommeparamtrelepointeur

surlazonelibreretnerenvoierien.
Lorsquonalloueunevariabletype,ondoitfaireuntranstypagedupointeurrenvoypar
pointeurdecetypedevariable.

malloc en

Pourutiliserlesfonctions malloc et free,vousdevezmettreaudbutdevotreprogrammelaligne:


#include <stdlib.h>

Sonrleestsimilaireceluidelaligne #include <stdio.h>.Vousverrezsasignificationdans


lechapitreconcernantleprprocesseur.
LexemplesuivantvavousprsenterunprogrammeCclassiquequimanipuledespointeurs.Cepro
grammeralisedesallocationsdynamiquesdemmoireet manipuleunelistedestructuresdyna
miquement, enfonctiondesentresquefait lutilisateur. Lestechniquesdesaisiesdeparamtres
prsentesdanslepremierchapitresontgalementrevues.Ceprogrammevousprsenteaussicom
mentpasserdesparamtresparvariable,soitpouroptimiserleprogramme,soitpourlesmodifierau
seindesfonctionsappeles.Enfin,lutilisationdumotclef const aveclespointeursestgalement
illustre.
Exemple413.AllocationdynamiquedemmoireenC
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*Autoriselutilisationdeprintf
etdescanf.*/
/*Autoriselutilisationdemalloc
etdefree.*/
/*Autoriselutilisationdestrcpy,
strlenetdestrcmp.*/

/*Typedebasedunlmentdelistedepersonne.*/
typedefstructperson
{
char*name;
/*Nomdelapersonne.*/
char*address;
/*Adressedelapersonne.*/
structperson*next; /*Pointeursurllmentsuivant.*/
}Person;
typedefPerson*People;

/*Typedelistedepersonnes.*/

/*Fonctionsdegestiondeslistesdepersonnes:*/
/*Fonctiondinitialisationdunelistedepersonne.
Lalisteestpasseparvariablepourpermettresoninitialisation.*/
voidinit_list(People*lst)
{

59

Chapitre4.Lespointeursetrfrences
*lst=NULL;
}
/*Fonctiondajoutdunepersonne.Lesparamtresdelapersonne
sontpasssparvariables,maisnepeuventtremodifiscar
ilssontconstants.CesontdeschanesdecaractresC,qui
sontdoncassimilesdespointeursdecaractresconstants.*/
intadd_person(People*lst,constchar*name,constchar*address)
{
/*Creunnouvellment:*/
Person*p=(Person*)malloc(sizeof(Person));
if(p!=NULL)
{
/*Allouelammoirepourlenometladresse.Attention,
ilfautcompterlecaractrenulterminaldeschanes:*/
p>name=(char*)malloc((strlen(name)+1)*sizeof(char));
p>address=(char*)malloc((strlen(address)+1)*sizeof(char));
if(p>name!=NULL&&p>address!=NULL)
{
/*Copielenometladresse:*/
strcpy(p>name,name);
strcpy(p>address,address);
p>next=*lst;
*lst=p;
}
else
{
free(p);
p=NULL;
}
}
return(p!=NULL);
}
/*Fonctiondesuppressiondunepersonne.
Lastructuredelalisteestmodifieparlasuppression
dellmentdecettepersonne.Celapeutimpliquerlamodification
duchanagedellmentprcdent,oulamodificationdelatte
delisteellemme.*/
intremove_person(People*lst,constchar*name)
{
/*Recherchelapersonneetsonantcdant:*/
Person*prev=NULL;
Person*p=*lst;
while(p!=NULL)
{
/*Onsortsillmentcourantestlapersonnerecherche:*/
if(strcmp(p>name,name)==0)
break;
/*Onpassellmentsuivantsinon:*/
prev=p;
p=p >next;
}
if(p!=NULL)
{
/*Lapersonneattrouve,onlasupprimedelaliste:*/
if(prev==NULL)

60

Chapitre4.Lespointeursetrfrences
{
/*Lapersonneestenttedeliste,onmetjour
lepointeurdettedeliste:*/
*lst=p >next;
}
else
{
/*Onmetjourleliendellmentprcdent:*/
prev>next=p>next;
}
/*etonladtruit:*/
free(p>name);
free(p>address);
free(p);
}
return(p!=NULL);
}
/*Simplefonctiondaffichage.*/
voidprint_list(Peopleconst*lst)
{
Personconst*p=*lst;
inti=1;
while(p!=NULL)
{
printf("Personne%d:%s(%s)\n",i,p
p=p >next;
++i;
}
}

>name,p>address);

/*Fonctiondedestructionetdelibrationdelammoire.*/
voiddestroy_list(People*lst)
{
while(*lst!=NULL)
{
Person*p=*lst;
*lst=p >next;
free(p>name);
free(p>address);
free(p);
}
return;
}
intmain(void)
{
intop=0;
size_ts;
charbuffer[16];
charname[256];
/*Creunelistedepersonne:*/
Peoplep;
init_list(&p);
/*Utiliselaliste:*/
do
{

61

Chapitre4.Lespointeursetrfrences
printf("Opration(0=quitter,1=ajouter,2=supprimer)?");
fgets(buffer,16,stdin);
buffer[15]=0;
op=3;
sscanf(buffer,"%d",&op);
switch(op)
{
case0:
break;
case1:
printf("Nom:");
fgets(name,256,stdin);
/*Litlenom.*/
name[255]=0;
/*Assurequelecaractrenul
terminalestcrit.*/
s=strlen(name);
/*Supprimelventuelsautdeligne.*/
if(name[s1]==\n)name[s1]=0;
/*Mmeoprationpourladresse:*/
printf("Adresse:");
fgets(address,256,stdin);
name[255]=0;
s=strlen(address);
if(address[s1]==\n)address[s1]=0;
add_person(&p,name,address);
break;
case2:
printf("Nom:");
fgets(name,256,stdin);
name[255]=0;
s=strlen(name);
if(name[s1]==\n)name[s1]=0;
if(remove_person(&p,name)==0)
{
printf("Personneinconnue.\n");
}
break;
default:
printf("Oprationinvalide\n");
break;
}
if(op!=0)print_list(&p);
}while(op!=0);
/*Dtruitlaliste:*/
destroy_list(&p);
return0;
}
Note: Commevouspouvezleconstater, lalecturedeschanesdecaractressaisiespar
lutilisateur est raliseaumoyendelafonction fgets delabibliothqueCstandard. Cette
fonctionpermet delireunelignecompltesur lefluxspcifientroisimeparamtre, et de
stockerlersultat danslachanedecaractresfournieenpremierparamtre. Ellenelirapas
plusdecaractresquelenombreindiquendeuximeparamtre,cequi permetdecontrlerla
tailledeslignessaisiesparlutilisateur.Lafonctionfgets ncessitemalheureusementquelques
traitementssupplmentairesavantdepouvoirutiliserlachanedecaractreslue,carellencrit
paslecaractrenulterminaldelachaneCsilenombremaximaldecaractreslireestatteint,
et ellestockelecaractredesaut deligneenfindelignesi cenombrenest pasatteint. Il
est doncncessairedesassurer quelaligneseterminebienpar uncaractrenul terminal
dunepart, et desupprimerlecaractredesaut delignesil nest pasessentiel dautrepart.

62

Chapitre4.Lespointeursetrfrences
Cestraitementsconstituent galement unbonexempledemanipulationdespointeurset
chanesdecaractres.

des

Ceprogrammeninterdit paslesdfinitionsmultiplesdepersonnesayant
lemmenom. Il
ninterdit pasnonplusladfinitiondepersonnesanonymes.
Lelecteur pourraessayer de
corrigercespetitsdfautstitredexercice, afindesassurerquelesnotionsdepointeursont
bienassimiles.RappelonsquelespointeurssontunenotionessentielleenCetquil fauttre
doncparfaitementfamiliarisaveceux.

4.11.2.AllocationdynamiqueenC++
Enplusdesfonctions malloc et free duC,leC++fournitdautresmoyenspouralloueretrestituer
lammoire.Pourcela,ildisposedoprateursspcifiques: new, delete, new[] et delete[].La
syntaxedecesoprateursestrespectivementlasuivante:
newtype
deletepointeur
newtype[taille]
delete[]pointeur

Lesdeuxoprateurs new et new[] permettentdallouerdelammoire,etlesdeuxoprateursdelete


et delete[] delarestituer.
Lasyntaxede new esttrssimple,ilsuffitdefairesuivrelemotclnew dutypedelavariableallouer,
etloprateurrenvoiedirectementunpointeursurcettevariableaveclebontype.Ilnestdoncplus
ncessairedeffectueruntranstypageaprslallocation,commectaitlecaspourlafonction malloc.
Parexemple,lallocationdunentiersefaitcommesuit:
int*pi=newint;

//quivalent(int*)malloc(sizeof(int)).

Lasyntaxede delete estencoreplussimple,puisquilsuffitdefairesuivrelemotcl delete du


pointeursurlazonemmoirelibrer:
deletepi;

//quivalentfree(pi);

Lesoprateurs new[] et delete[] sontutilisspouralloueretrestituerlammoirepourlestypes


tableaux.Cenesontpaslesmmesoprateursque new et delete,etlammoirealloueparlesuns
nepeutpastrelibreparlesautres.Silasyntaxede delete[] estlammequecellededelete,
lemploideloprateur new[] ncessitededonnerlatailledutableauallouer.Ainsi,onpourracrer
untableaude10000entiersdelamaniresuivante:
int*Tableau=newint[10000];

etdtruirecetableaudelamaniresuivante:
delete[]Tableau;

63

Chapitre4.Lespointeursetrfrences
Loprateur new[] permetgalementdallouerdestableauxplusieursdimensions.Pourcela,ilsuffit
despcifierlestaillesdesdiffrentesdimensionslasuitedutypededonnedeslementsdutableau,
exactementcommelorsqueloncreuntableaustatiquement.Toutefois,seulelapremiredimension
dutableaupeut trevariable, et lesdimensionsdeuxet suivantesdoivent avoirunetailleentire
positiveetconstante.Parexemple,seuleladeuximelignedelexemplequisuitestuneallocation
dynamiquedetableauvalide:
inti=5,j=3;
int(*pi1)[3]=newint[i][3];//Alloueuntableaudeilignesdetroisentiers.
int(*pi2)[3]=newint[i][j];//Illgal,jnestpasconstant.

Silondsirerellementavoirdestableauxdontplusieursdimensionssontdetaillevariable,ondevra
alloueruntableaudepointeurset,pourchaquelignedecetableau,allouerunautretableaulamain.
Note:Ilestimportantdutiliserloprateurdelete[] aveclespointeursrenvoysparloprateur
new[] et loprateur delete aveclespointeursrenvoyspar new. Deplus, onnedevrapas
nonplusmlangerlesmcanismesdallocationmmoireduCet duC++(utiliser delete sur
unpointeurrenvoypar malloc parexemple).Eneffet,lecompilateurpeutallouerunequantit
demmoiresuprieurecelledemandeparleprogrammeafindestockerdesdonnesqui
lui permettentdegrerlammoire. Cesdonnespeuvent treinterprtesdiffremment pour
chacunedesmthodesdallocation,sibienquuneutilisationerronepeutentranersoitlaperte
desblocsdemmoire,soituneerreur,soitunplantage.

Loprateur new[] allouelammoireetcrelesobjetsdanslordrecroissantdesadresses.Inverse


ment,loprateur delete[] dtruitlesobjetsdutableaudanslordredcroissantdesadressesavant
delibrerlammoire.
Lamaniredontlesobjetssontconstruitsetdtruitsparlesoprateurs new et new[] dpenddeleur
nature.Silsagitdetypesdebasedulangageoudestructuressimples,aucuneinitialisationparticu
lirenestfaite.Lavaleurdesobjetsainsicrsestdoncindfinie,etilfaudraraliserlinitialisation
soimme.Si,enrevanche,lesobjetscrssontdesinstancesdeclassesC++,leconstructeurdeces
classesseraautomatiquementappellorsdeleurinitialisation.Cestpourcetteraisonquelonde
vra,demaniregnrale,prfrerlesoprateursC++dallocationetdedsallocationdelammoire
auxfonctions malloc et free duC.Cesoprateursontdepluslavantagedepermettreunmeilleur
contrledestypesdedonnesetdviteruntranstypage.
Lesnotionsdeclasseetdeconstructeur
serontprsentesendtaildanslechapitretraitantdelacoucheobjetduC++.
Lorsquilnyapasassezdemmoiredisponible,lesoprateursnew et new[] peuventsecomporterde
deuxmaniresselonlimplmentation.Lecomportementleplusrpanduestderenvoyerunpointeur
new manquede
nul. Cependant, lanormeC++indiqueuncomportementdiffrent:siloprateur
mmoire, ildoitappelerungestionnairederreur. Cegestionnaireneprendaucunparamtreetne
renvoierien.Selonlecomportementdecegestionnairederreur,plusieursactionspeuventtrefaites:

64

soit cegestionnairepeut corrigerlerreurdallocationet rendrelamainloprateur new (le


programmenestdoncpastermin),quieffectueunenouvelletentativepourallouerlammoire
demande;

soit il nepeut rienfaire. Danscecas, il peut mettrefinlexcutionduprogrammeoulancer


uneexception std::bad_alloc,quiremontealorsjusqulafonctionappelantloprateur new.
Cestlecomportementdugestionnaireinstallpardfautdanslesimplmentationsconformesla
norme.

Chapitre4.Lespointeursetrfrences
Loprateur new estdoncsusceptibledelanceruneexception std::bad_alloc.VoirleChapitre9
pourplusdedtailscesujet.
Ilestpossiblederemplacerlegestionnairederreurappelparloprateur new laidedelafonction
std::set_new_handler,dclaredanslefichierdenttenew.Cettefonctionattendenparamtre
unpointeursurunefonctionquineprendaucunparamtreetnerenvoierien.Ellerenvoieladresse
dugestionnairederreurprcdent.
Note:Lafonction std::set_new_handler et laclassestd::bad_allocfont partiedelabiblio
thquestandardC++. Commeleursnomslindiquent, ilssont dclarsdanslespacedenom
mage std::,quiestrservpourlesfonctionsetlesclassesdelabibliothquestandard.Voyez
aussi leChapitre11pourplusdedtailssurlesespacesdenommages.Sivousnedsirezpas
new.h
utiliserlesmcanismesdesespacesdenommage,vousdevrezinclurelefichierdentte
aulieude new.
Attendezvouscequunjour, touslescompilateursC++lancent uneexceptionencasde
manquedemmoirelorsdelappel loprateur new,carcestcequimposelanorme.Si vous
nedsirezpasavoirgrerlesexceptionsdansvotreprogrammeet
continuerrecevoirun
pointeurnulencasdemanquedemmoire,vouspouvezfournirundeuximeparamtredetype
std::nothrow_tloprateur new.Labibliothquestandarddfinitlobjetconstant std::nothrow
cetusage.

Lesoprateurs delete et delete[] peuventparfaitementtreappelsavecunpointeurnulenpara


mtre.Danscecas,ilsnefontrienetredonnentlamainimmdiatementlappelant.Ilnestdoncpas
ncessairedetesterlanonnullitdespointeurssurlesobjetsquelondsiredtruireavantdappeler
lesoprateurs delete et delete[].

4.12.Pointeursetrfrencesdefonctions
4.12.1.Pointeursdefonctions
Il est possibledefairedespointeursdefonctions. Unpointeurdefonctioncontient ladressedu
dbutducodebinaireconstituantlafonction.Ilestpossibledappelerunefonctiondontladresseest
contenuedansunpointeurdefonctionavecloprateurdindirection*.
Pourdclarerunpointeurdefonction,ilsuffitdeconsidrerlesfonctionscommedesvariables.Leur
dclarationestidentiquecelledestableaux,enremplaantlescrochetspardesparenthses:
type(*identificateur)(paramtres);

o type estletypedelavaleurrenvoyeparlafonction, identificateur estlenomdupoin


teurdelafonctionet paramtres estlalistedestypesdesvariablesquelafonctionattendcomme
paramtres,sparspardesvirgules.
Exemple414.Dclarationdepointeurdefonction
int(*pf)(int,int);

/*Dclareunpointeurdefonction.*/

pf estunpointeurdefonctionattendantcommeparamtresdeuxentiersetrenvoyantunentier.

Ilestpossibledutiliser typedef pourcrerunaliasdutypepointeurdefonction:

65

Chapitre4.Lespointeursetrfrences
typedefint(*PtrFonct)(int,int);
PtrFonctpf;

PtrFonct estletypedespointeursdefonctions.

Si f estunefonctionrpondantcescritres, onpeutalorsinitialiser pf avecladressede f. De


mme,onpeutappelerlafonctionpointepar pf avecloprateurdindirection.
Exemple415.Drfrencementdepointeurdefonction
#include <stdio.h>

/*Autoriselemploidescanfetdeprintf.*/

intf(inti,intj)
{
returni+j;
}

/*Dfinitunefonction.*/

int(*pf)(int,int);

/*Dclareunpointeurdefonction.*/

intmain(void)
{
intl,m;
/*Dclaredeuxentiers.*/
pf=&f;
/*Initialisepfavecladressedelafonctionf.*/
printf("Entrezlepremierentier:");
scanf("%u",&l);
/*Initialiselesdeuxentiers.*/
printf("\nEntrezledeuximeentier:");
scanf("%u",&m);
/*Utiliselepointeurpfpourappelerlafonctionf
etaffichelersultat:*/
printf("\nLeursommeestde:%u\n",(*pf)(l,m));
return0;
}

Lintrtdespointeursdefonctionestdepermettrelappeldunefonctionparmiunventaildefonc
tionsauchoix.
Parexemple,ilestpossibledefaireuntableaudepointeursdefonctionsetdappelerlafonctiondont
onconnatlindicedesonpointeurdansletableau.
Exemple416.Applicationdespointeursdefonctions
#include <stdio.h>

/*Autoriselemploidescanfetdeprintf.*/

/*Dfinitplusieursfonctionstravaillantsurdesentiers:*/
intsomme(inti,intj)
{
returni+j;
}
intmultiplication(inti,intj)
{
returni*j;
}

66

Chapitre4.Lespointeursetrfrences

intquotient(inti,intj)
{
returni/j;
}
intmodulo(inti,intj)
{
returni%j;
}
typedefint(*fptr)(int,int);
fptrftab[4];
intmain(void)
{
inti,j,n;
ftab[0]=&somme;
/*Initialiseletableaudepointeur*/
ftab[1]=&multiplication;/*defonctions.*/
ftab[2]=&quotient;
ftab[3]=&modulo;
printf("Entrezlepremierentier:");
scanf("%u",&i);
/*Demandelesdeuxentiersietj.*/
printf("\nEntrezledeuximeentier:");
scanf("%u",&j);
printf("\nEntrezlafonction:");
scanf("%u",&n);
/*Demandelafonctionappeler.*/
if(n < 4)
printf("\nRsultat:%u.\n",(*(ftab[n]))(i,j));
else
printf("\nMauvaisnumrodefonction.\n");
return0;
}

4.12.2.Rfrencesdefonctions
Lesrfrencesdefonctionssont acceptesenC++. Cependant, leurusageest assezlimit. Elles
permettentparfoisdesimplifierlescrituresdanslesmanipulationsdepointeursdefonctions.Mais
commeilnestpaspossiblededfinirdestableauxderfrences, leprogrammedexempledonn
cidessusnepeutpastrercritavecdesrfrences.
Lesrfrencesdefonctionspeuventmalgrtouttreutilisesprofitdanslepassagedesfonctions
enparamtredansuneautrefonction.Parexemple:
#include <stdio.h>

//Autoriselemploidescanfetdeprintf.

//Fonctiondecomparaisondedeuxentiers:
intcompare(inti,intj)
{
if(i<j)return1;
elseif(i>j)return1;
elsereturn0;
}

67

Chapitre4.Lespointeursetrfrences
//Fonctionutilisantunefonctionentantqueparamtre:
voidtrie(inttableau[],inttaille,int(&fcomp)(int,int))
{
//Effectueletridetableauaveclafonctionfcomp.
//Cettefonctionpeuttreappelecommetoutelesautres
//fonctions:
printf("%d",fcomp(2,3));
.
.
.
return;
}
intmain(void)
{
intt[3]={1,5,2};
trie(t,3,compare);
return0;
}

//Passagedecompare()enparamtre.

4.13.Paramtresdelafonctionmainlignede
commande
Lappeldunprogrammesefaitnormalementaveclasyntaxesuivante:
nomparam1param2[...]

o nom estlenomduprogrammeappeleret param1,etc.sontlesparamtresdelalignedecom


mande.Deplus,leprogrammeappelpeutrenvoyeruncodederreurauprogrammeappelant(soit
lesystmedexploitation,soitunautreprogramme).Cecodederreurestengnral 0 quandlepro
grammesestdroulcorrectement.Touteautrevaleurindiquequuneerreursestproduiteencours
dexcution.
Lavaleurducodederreurestrenvoyeparlafonction main.Lecodederreurdoittoujourstreun
entier.Lafonction main peutdonc(etmmenormalementdoit)tredetypeentier:
intmain(void)...

Lesparamtresdelalignedecommandespeuventtrercuprsparlafonctionmain.Sivousdsirez
lesrcuprer,lafonction main doitattendredeuxparamtres:

lepremierestunentier,quireprsentelenombredeparamtres;

ledeuximeestuntableaudechanesdecaractres(doncenfaituntableaudepointeurs,ouencore
unpointeurdepointeursdecaractres).

Lesparamtressercuprentaveccetableau.Lepremierlmentpointetoujourssurlachanedon
nantlenomduprogramme.Lesautreslmentspointentsurlesparamtresdelalignedecommande.

68

Chapitre4.Lespointeursetrfrences
Exemple417.Rcuprationdelalignedecommande
#include <stdio.h>

/*Autoriselutilisationdesfonctions*/
/*printfetscanf.*/

intmain(intn,char*params[]) /*Fonctionprincipale.*/
{
inti;
/*Affichelenomduprogramme:*/
printf("Nomduprogramme:%s.\n",params[0]);
/*Affichelalignedecommande:*/
for(i=1;i <n;++i)
printf("Argument%d:%s.\n",i,params[i]);
return0;
/*Toutsestbienpass:onrenvoie0!*/
}

4.14.DANGER
Lespointeurssont,commeonlavu,trsutilissenC/C++.Ilfautdoncbiensavoirlesmanipuler.
Maisilssonttrsdangereux,carilspermettentdaccdernimportequellezonemmoire,silsne
sontpascorrectementinitialiss.Danscecas,ilspointentnimporteo.Accderlammoireavec
unpointeurnoninitialispeutaltrersoitlesdonnesduprogramme,
soitlecodeduprogramme
luimme,soitlecodedunautreprogrammeouceluidusystmedexploitation.Celaconduitdans
lamajoritdescasauplantageduprogramme,etparfoisauplantagedelordinateursilesystmene
disposepasdemcanismesdeprotectionefficaces.
VEILLEZTOUJOURSINITIALISERLESPOINTEURSQUEVOUS
UTILISEZ.

Pourinitialiserunpointeurquinepointesurrien(cestlecaslorsquelavariablepointenestpas
encorecreoulorsquelleestinconnuelorsdeladclarationdupointeur),onutiliseralepointeur
prdfini NULL.
VRIFIEZQUETOUTEDEMANDEDALLOCATIONMMOIREAT
SATISFAITE.

Lafonction malloc renvoielepointeur NULL lorsquilnyaplusoupasassezdemmoire.Lecom


portementdesoprateurs new et new[] estdiffrent.Thoriquement,ilsdoiventlanceruneexception
silademandedallocationmmoirenapasputresatisfaite.Cependant,certainscompilateursfont
ensortequilsrenvoientlepointeurnuldutypedelobjetcrer.
Silsrenvoientuneexception,leprogrammeseraarrtsiaucuntraitementparticuliernestfait.Bien
entendu,leprogrammepeuttraitercetteexceptionsilledsire,maisengnral,ilnyapasgrand
chosefaireencasdemanquedemmoire.Vouspouvezconsulterlechapitretraitantdesexceptions
pourplusdedtailscesujet.

69

Chapitre4.Lespointeursetrfrences
Danstouslescas,
LORSQUONUTILISEUNPOINTEUR,ILFAUTVRIFIERSILESTVALIDE

(paruntestavec NULL oulepointeurnul,ouenanalysantlalgorithme).Cettevrificationinclutle


testdedbordementlorsdesaccsauxchanesdecaractresetauxtableaux.Celaestextrmement
importantlorsquelonmanipuledesdonnesprovenantdelextrieurduprogramme,caronnepeut
danscecaspassupposerquecesdonnessontvalides.

70

Chapitre5.LeprprocesseurC
5.1.Dfinition
Leprprocesseurestunprogrammequianalyseunfichiertexteetquiluifaitsubircertainestransfor
mations.Cestransformationspeuventtrelinclusiondunfichier,lasuppressiondunezonedetexte
ouleremplacementdunezonedetexte.
Leprprocesseur effectuecesoprationsensuivant
danalyse.

desordresquil lit danslefichier encours

Il est appelautomatiquement parlecompilateur, avant lacompilation, pourtraiterlesfichiers


compiler.

5.2.Lescommandesduprprocesseur
Touteslescommandesduprprocesseurcommencent:

endbutdeligne;

parunsignedise( #).

Lescommandessontlessuivantes:

5.2.1.Inclusiondefichier
Linclusiondefichierpermetdefactoriserdutextecommunplusieursautresfichiers(parexemple
desdclarationsdetype,deconstante,defonction,etc.).Letextecommunestmisengnraldansun
fichierportantlextension .h (pourheader,fichierdenttedeprogramme).
Syntaxe:
#include"fichier"

ou:
#include <fichier>

fichier estlenomdufichierinclure.Lorsquesonnomestentreguillemets,lefichierspcifiest

recherchdanslerpertoirecourant(normalementlerpertoireduprogramme).Silestencadrde
crochets,ilestrecherchdaborddanslesrpertoiresspcifisenlignedecommandeavecloption
I,puisdanslesrpertoiresducheminderecherchedesenttesdusystme(cesrglesnesontpas
fixes,ellesnesontpasnormalises).
Lefichierinclusesttraitluiaussiparleprprocesseur.
Lasignificationdelaligne #include <stdio.h> audbutdetouslesprogrammesutilisantles
fonctions scanf et printf devientalorsclaire.Sivousouvrezlefichier stdio.h,vousyverrezla
dclarationdetouteslesfonctionsetdetouslestypesdelabibliothquedentresortiestandard.De

71

Chapitre5.LeprprocesseurC
mme,lesfonctions malloc et free sontdclaresdanslefichierdentte stdlib.h etdfinies
danslabibliothquestandard.Linclusiondecesfichierspermetdoncdedclarercesfonctionsafin
delesutiliser.

5.2.2.Constantesdecompilationetremplacementdetexte
Leprprocesseurpermetdedfinirdesidentificateursqui,utilissdansleprogramme,serontrempla
cstextuellementparleurvaleur.Ladfinitiondecesidentificateurssuitlasyntaxesuivante:
#defineidentificateurtexte

o identificateur estlidentificateurquiserautilisdanslasuiteduprogramme,et texte sera


letextederemplacementqueleprprocesseurutilisera.Letextederemplacementestfacultatif(dans
cecas,cestletextevide).chaquefoisquelidentificateur identificateur serarencontrparle
prprocesseur,ilseraremplacparletexte texte danstoutelasuiteduprogramme.
Cettecommandeestcourammentutilisepourdfinirdesconstantesdecompilation,cestdiredes
constantesquidcriventlesparamtresdelaplateformepourlaquelleleprogrammeestcompil.Ces
constantespermettentderaliserdescompilationsconditionnelles,cestdiredemodifierlecom
portementduprogrammeenfonctiondeparamtresdfinislorsdesacompilation.Elleestgalement
utilisepourremplacerdesidentificateursduprogrammepardautresidentificateurs,
parexemple
afindetesterplusieursversionsdunemmefonctionsansmodifiertoutleprogramme.
Exemple51.Dfinitiondeconstantesdecompilation
#defineUNIX_SOURCE
#definePOSIX_VERSION1001

Danscetexemple,lidentificateur UNIX_SOURCE seradfinidanstoutelasuiteduprogramme,etla


constantedecompilation POSIX_VERSION seraremplacepar 1001 partoutoelleapparatra.
Note:Onferaunedistinctionbiennetteentrelesconstantesdecompilationdfiniesavecla
directive #define duprprocesseuret lesconstantesdfiniesaveclemot cl const. Enef
fet, lesconstanteslittralesnerservent pasdemmoire. Cesont desvaleursimmdiates,
dfiniesparlecompilateur. Enrevanche, lesvariablesdeclassedestockage const peuvent
malgrtoutavoiruneplacemmoirerserve.Cepeutparexempletrelecassilonmanipule
leuradresseousil nesagitpasdevraiesconstantes,parexemplesi ellespeuventtremodi
fiesparlenvironnement(danscecas,ellesdoiventtredclaresaveclaclassedestockage
volatile).Cesontdoncplusdesvariablesaccessiblesenlectureseulequedesconstantes.On
nepourrajamaissupposerquunevariablenechangepasdevaleursousprtextequelleala
classedestockage const,alorsquvidemment,uneconstantelittraledclareavecladirective
#define duprprocesseurconserveratoujourssavaleur(pourvuquonnelaredfinissepas).
Parailleurs, lesconstanteslittralesnont pasdetype, cequi peut tretrsgnant et source
derreur. Onrserveradoncleuremploi uniquement pourlesconstantesdecompilation, et on
prfreralemotcl const pourtouteslesautresconstantesduprogramme.

Leprprocesseurdfinituncertainnombredeconstantesdecompilationautomatiquement.Cesont
lessuivantes:

__LINE__ :donnelenumrodelalignecourante;
__FILE__ :donnelenomdufichiercourant;

72

Chapitre5.LeprprocesseurC
__DATE__ :renvoieladatedutraitementdufichierparleprprocesseur;
__TIME__ :renvoielheuredutraitementdufichierparleprprocesseur;

: dfinieuniquement danslecasdunecompilationC++.
Savaleur doit tre
denormedu2dcembre1996. En
pratique, savaleur est dpendantedelimplmentationutilise, maisonpourrautiliser cette
chanederemplacementpourdistinguerlespartiesdecodecritesenC++decellescritesenC.

__cplusplus

199711L pourlescompilateurscompatiblesavecleprojet

Note:Si __FILE__ , __DATE__, __TIME__ et __cplusplus sont biendesconstantespourun


fichierdonn,cenestpaslecasde __LINE__ .Eneffet,cettedernireconstantechangebien
videmmentdevaleurchaqueligne.Onpeutconsidrerquelleestredfinieautomatiquement
parleprprocesseurchaquedbutdeligne.

5.2.3.Compilationconditionnelle
Ladfinitiondesidentificateursetdesconstantesdecompilationesttrsutilisepoureffectuerce
quelonappellelacompilationconditionnelle. Lacompilationconditionnelleconsisteremplacer
certainesportionsdecodesourcepardautres,enfonctiondelaprsenceoudelavaleurdeconstantes
decompilation.Celaestralisablelaidedesdirectivesdecompilationconditionnelle,dontlaplus
couranteestsansdoute #ifdef :
#ifdefidentificateur
.
.
.
#endif

Danslexempleprcdent,letextecomprisentrele #ifdef (cestdireifdefined)etle #endif


estlaisstelquelsilidentificateur identificateur estconnuduprprocesseur.Sinon,ilestsup
prim.Lidentificateurpeuttredclarenutilisantsimplementlacommande #define vueprc
demment.
Ilexistedautresdirectivesdecompilationconditionnelle:
#ifndef
#elif
#if

(ifnotdefined...)
(sinon,si...)
(si...)

Ladirective #if attendenparamtreuneexpressionconstante.Letextequilasuitestinclusdansle


fichiersietseulementsicetteexpressionestnonnulle.Parexemple:
#if(__cplusplus==199711L)
.
.
.
#endif

permetdinclureunmorceaudecodeC++strictementconformelanormedcritedansleprojetde
normedu2dcembre1996.
Uneautreapplicationcourantedesdirectivesdecompilationestlaprotectiondesfichiersdentte
contrelesinclusionsmultiples:

73

Chapitre5.LeprprocesseurC
#ifndefDejaLa
#defineDejaLa
Texteninclurequuneseulefoisauplus.
#endif

Celapermetdviterqueletextesoitinclusplusieursfois,lasuitedeplusieursappelsde #include.
Eneffet,aupremierappel, DejaLa nestpasconnuduprprocesseur.Ilestdoncdclaretletexte
estinclus. Lorsdetoutautreappelultrieur, DejaLa existe, etletextenestpasinclus. Cegenre
dcritureserencontredanslesfichiersdentte, pourlesquelsengnral onneveut pasquune
inclusionmultipleaitlieu.

5.2.4.Autrescommandes
Leprprocesseurestcapabledeffectuerdautresactionsquelinclusionetlasuppressiondetexte.
Lesdirectivesquipermettentdeffectuercesactionssontindiquescidessous:
#

:nefaitrien(directivenulle);

#errormessage

:permetdestopperlacompilationenaffichantlemessagederreurdonnen

paramtre;
#linenumro[fichier]:permetdechangerlenumrodelignecourantetlenomdufichier

courantlorsdelacompilation;
#pragmatexte :permetdedonnerdesordresspcifiquesunelimplmentationducompilateur

toutenconservantlaportabilitduprogramme.Touteimplmentationquinereconnatpasunordre
donndansunedirective #pragma doitlignorerpourviterdesmessagesderreurs.Leformatdes
ordresquelonpeutspcifierlaidedeladirective #pragma nestpasnormalisetdpendde
chaquecompilateur.

5.3.Lesmacros
Leprprocesseurpeut,lorsdumcanismederemplacementdetexte,utiliserdesparamtresfournis
lidentificateurremplacer.Cesparamtressontalorsreplacssansmodificationdansletextede
remplacement.Letextederemplacementestalorsappelmacro.
Lasyntaxedesmacrosestlasuivante:
#definemacro(paramtre[,paramtre[...]])dfinition

Exemple52.MacrosMINetMAX
#defineMAX(x,y)((x)>(y)?(x):(y))
#defineMIN(x,y)((x)<(y)?(x):(y))

74

Chapitre5.LeprprocesseurC
Note:Pourpoursuivreunedfinitionsurlalignesuivante,terminezlalignecouranteparlesigne
\.

Lemcanismedesmacrospermetdefairelquivalentdefonctionsgnrales,quifonctionnentpour
touslestypes.Ainsi,lamacro MAX renvoielemaximumdesesdeuxparamtres,quilssoiententiers,
longsourels. Cependant, onprendragardeaufait quelesparamtrespasssunemacrosont
valusparcellecichaquefoisquilssontutilissdansladfinitiondelamacro.Celapeutposer
desproblmesdeperformancesou, pire, provoquerdeseffetsdebordsindsirables. Parexemple,
lutilisationsuivantedelamacro MIN :
MIN(f(3),5)

provoqueleremplacementsuivant:
((f(3))<(5))?(f(3)):(5))

soitdeuxappelsdelafonction f si f(3) estinfrieur 5,etunseulappelsinon.Silafonctionf ainsi


appelemodifiedesvariablesglobales,lersultatdelamacroneseracertainementpasceluiattendu,
puisquelenombredappelsestvariablepourunemmeexpression.Onviteradonc,autantquefaire
sepeut,dutiliserdesexpressionsayantdeseffetsdebordsenparamtresdunemacro.Lescritures
dutype:
MIN(++i,j)

sontdoncprohiber.
Onmettratoujoursdesparenthsesautourdesparamtresdelamacro.
Eneffet, cesparamtres
peuventtredesexpressionscomposes, quidoiventtrecalculescompltementavantdtreuti
lisesdanslamacro.Lesparenthsesforcentcecalcul.Sionnelesmetpas,lesrglesdepriorits
peuventgnreruneerreurdelogiquedanslamacroellemme.Demme,onentoureradeparen
thseslesmacrosrenvoyantunevaleur,afindeforcerleurvaluationcomplteavanttouteutilisation
dansuneautreexpression.Parexemple:
#definemul(x,y)x*y

estunemacrofausse.Laligne:
mul(2+3,5+9)

seraremplacepar:
2+3*5+9

cequivaut 26,etnonpas 70 commeonlauraitattendu.Labonnemacroest:


#definemul(x,y)((x)*(y))

carelledonneletextesuivant:
((2+3)*(5+9))

etlersultatestcorrect.Demme,lamacro:

75

Chapitre5.LeprprocesseurC
#defineadd(x,y)(x)+(y)

estfausse,carlexpressionsuivante:
add(2,3)*5

estremplacetextuellementpar:
(2)+(3)*5

dontlersultatest 17 etnon 25 commeonlauraitespr.Cettemacrodoitdoncsedclarercomme


suit:
#defineadd(x,y)((x)+(y))

Ainsi,lesparenthsesassurentuncomportementcohrentdelamacro.Commeonlevoit,lesparen
thsespeuventalourdirlesdfinitionsdesmacros,maisellessontabsolumentncessaires.
Lersultatduremplacementdunemacroparsadfinitionest,
luiaussi, soumisauprprocesseur.
Parconsquent, unemacropeut utiliseruneautremacroouuneconstantedfinieavec #define.
Cependant,cemcanismeestlimitauxmacrosquinontpasencoretremplacesafindviterune
rcursioninfinieduprprocesseur.Parexemple:
#definetoto(x)toto((x)+1)
toto(3) , letextederemplacement final sera
dfinit lamacro toto. Si plusloinonutilise
toto((3)+1) etnonpaslexpressioninfinie (...(((3)+1)+1...)+1 .

Leprprocesseurdfinitautomatiquementlamacro defined,quipermetdetestersiunidentificateur
estconnuduprprocesseur.Sasyntaxeestlasuivante:
defined(identificateur)

Lavaleurdecettemacroest 1 silidentificateurexiste, 0 sinon.Elleestutiliseprincipalementavec


ladirective #if.Ilestdoncquivalentdcrire:
#ifdefined(identificateur)
.
.
.
#endif

et:
#ifdefidentificateur
.
.
.
#endif

Cependant, defined permetlcrituredexpressionspluscomplexesqueladirective #if.

76

Chapitre5.LeprprocesseurC

5.4.Manipulationdechanesdecaractresdansles
macros
Leprprocesseurpermetdeffectuerdesoprationssurleschanesdecaractres.Toutargumentde
macropeuttretransformenchanedecaractresdansladfinitiondelamacrosilestprcddu
signe #.Parexemple,lamacrosuivante:
#defineCHAINE(s)#s

transformesonargumentenchanedecaractres.Parexemple:
CHAINE(2+3)

devient:
"2+3"

Lorsdelatransformationdelargument,touteoccurrencedescaractres " et \ esttransformeres


pectivementen \" et \\ pourconservercescaractresdanslachanedecaractresderemplacement.
Leprprocesseurpermetgalementlaconcatnationdetextegrceloprateur ##.Lesarguments
delamacroquisontsparsparcetoprateursontconcatns(sanstretransformsenchanesde
caractrescependant).Parexemple,lamacrosuivante:
#defineNOMBRE(chiffre1,chiffre2)chiffre1##chiffre2

permetdeconstruireunnombredeuxchiffres:
NOMBRE(2,3)

est remplacparlenombredcimal 23. Lersultat delaconcatnationest ensuiteanalyspour


dventuelsremplacementsadditionnelsparleprprocesseur.

5.5.Lestrigraphes
LejeudecaractresutilisparlelangageC++comprendtoutesleslettresenmajusculesetenminus
cules,tousleschiffresetlescaractressuivants:
.,;:!?"+^*%=&

|~_#/\{}[]()

<>

Malheureusement,certainsenvironnementssontincapablesdegrerquelquesunsdecescaractres.
Cestpourrsoudreceproblmequelestrigraphesonttcrs.
Lestrigraphessontdessquencesdetroiscaractrescommenantpardeuxpointsdinterrogations.Ils
permettentderemplacerlescaractresquinesontpasaccessiblessurtouslesenvironnements.Vous
nutiliserezdoncsansdoutejamaislestrigraphes,moinsdytreforc.Lestrigraphesdisponibles
sontdfiniscidessous:

77

Chapitre5.LeprprocesseurC
Tableau51.Trigraphes

78

Trigraphe

Caractrederemplacement

??=

??/

??

??(

??)

??!

??<

??>

??

Chapitre6.Modularitdesprogrammeset
gnrationdesbinaires
Lamodularitest lefait, pourunprogramme, dtrecrit enplusieursmorceauxrelativement in
dpendantslesunsdesautres. Lamodularitadnormesavantageslorsdudveloppement dun
programme. Cependant, elleimpliqueunprocessusdegnrationdelexcutableassezcomplexe.
Danscechapitre,nousallonsvoirlintrtdelamodularit,lesdiffrentestapesquipermettentla
gnrationdelexcutableetlinfluencedecestapessurlasyntaxedulangage.

6.1.Pourquoifaireuneprogrammationmodulaire?
Cequicotelepluschereninformatique, cestledveloppementdelogiciel, paslematriel. En
effet, dvelopperunlogiciel demandedutemps, delamaindoeuvrequalifie, et nest pasfacile
(ilyatoujoursdeserreurs).Deplus,leslogicielsdveloppssontsouventspcifiquesuntypede
problmedonn.Pourchaqueproblme,ilfauttoutrefaire.
Cenestpasuntrsbonbilan.Pourvitertouscesinconvnients,unebranchedelinformatiquea
tdveloppe:legnielogiciel.Legnielogicieldonnelesgrandsprincipesappliquerlorsdela
ralisationdunprogramme,delaconceptionladistribution,etsurtouteladuredevieduprojet.
Cesujetdpasselargementlecadredececours,
aussijeneparleraisquedelaspectcodageseul,
cestdirecequiconcerneleC/C++.
Auniveauducodage,leplusimportantestlaprogrammationmodulaire.Lesidesquiensontla
basesontlessuivantes:

diviserletravailenplusieursquipes;

crerdesmorceauxdeprogrammeindpendantsdelaproblmatiqueglobale,
pourdautreslogiciels;

supprimerlesrisquesderreursquonavaitenreprogrammantcesmorceauxchaquefois.

doncrutilisables

Jetiensprciserquelesprincipesdelaprogrammationmodulairenesappliquentpasquauxpro
grammesdveloppspardesquipesdeprogrammeurs. Ilssappliquent aussi auxprogrammeurs
individuels. Eneffetilestplusfacilededcomposerunproblmeenseslments, forcmentplus
simples,quedeletraiterdanssatotalit(dixitDescartes).
Pourparvenircebut,ilestindispensabledepouvoirdcouperunprogrammeensousprogrammes
indpendants,oupresqueindpendants.Pourquechacunpuissetravaillersursapartiedeprogramme,
ilfautquecesmorceauxdeprogrammesoientdansdesfichiersspars.
Pourpouvoirvrifiercesmorceauxdeprogramme,ilfautquelescompilateurspuissentlescompiler
indpendamment, sansavoirlesautresfichiersduprogramme. Ainsi, ledveloppementdechaque
fichierpeutsefairerelativementindpendammentdeceluidesautres.Cependant,cettedivisiondu
travailimpliquedesoprationsassezcomplexespourgnrerlexcutable.

79

Chapitre6.Modularitdesprogrammesetgnrationdesbinaires

6.2.Lesdiffrentesphasesduprocessusde
gnrationdesexcutables
Lesphasesduprocessusquiconduisentlexcutablepartirdesfichierssourcesdunprogramme
sontdcritescidessous.CesphasesnesontengnralpasspcifiquesauC++,etmmesilesdif
frentsoutilsdeprogrammationpeuventlescacher, leprocessusdegnrationdesexcutablesse
drouletoujoursselonlesprincipesquisuivent.
Audbutdelagnrationdelexcutable,onnedisposequedesfichierssourcesduprogramme,crit
enC,C++outoutautrelangage(cequisuitnestpasspcifiqueauC/C++).Engnral,lapremire
tapeestletraitementdesfichierssourcesavantcompilation.DanslecasduCetduC++,ilsagitdes
oprationseffectuesparleprprocesseur(remplacementdemacros,suppressiondetexte,inclusion
defichiers...).
Vientensuitelacompilationspare,quiestlefaitdecompilersparmentlesfichierssources.Le
rsultatdelacompilationdunfichiersourceestgnralementunfichierenassembleur,cestdirele
langagedcrivantlesinstructionsdumicroprocesseurdelamachineciblepourlaquelleleprogramme
estdestin.Lesfichiersenassembleurpeuventtretraduitsdirectementencequelonappelledes
fichiersobjets.Lesfichiersobjetscontiennentlatraductionducodeassembleurenlangagemachine.
Ilscontiennentaussidautresinformations,parexemplelesdonnesinitialisesetlesinformations
quiserontutiliseslorsdelacrationdufichierexcutablepartirdetouslesfichiersobjetsgnrs.
Lesfichiersobjetspeuventtreregroupsenbibliothquesstatiques, afinderassembleruncertain
nombredefonctionnalitsquiserontutilisesultrieurement.
Enfin,ltapefinaleduprocessusdecompilationestleregroupementdetouteslesdonnesetdetoutle
codedesfichiersobjetsduprogrammeetdesbibliothques(fonctionsdelabibliothqueCstandardet
desautresbibliothquescomplmentaires),ainsiquelarsolutiondesrfrencesinterfichiers.Cette
tapeestappeleditiondeliens(linkingenanglais).Lersultatdelditiondeliensestlefichier
image,quipourratrechargenmmoireparlesystmedexploitation.Lesfichiersexcutableset
lesbibliothquesdynamiquessontdesexemplesdefichiersimage.

80

Chapitre6.Modularitdesprogrammesetgnrationdesbinaires
Figure61.Processusdegnrationdesbinaires

Toutescesoprationspeuventtrergroupesenuneseuletapeparlesoutilsutiliss.Ainsi,lescom
pilateursappellentgnralementleprprocesseuretlassembleurautomatiquement,etralisentpar
foismmelditiondelienseuxmmes.Toutefois,ilrestegnralementpossible,laidedoptions
spcifiqueschaqueoutildedveloppement, dedcomposerlesdiffrentestapesetdobtenirles
fichiersintermdiaires.
Enraisondunombredefichiersimportantetdesdpendancesquipeuventexisterentreeux,lepro
cessusdegnrationdunprogrammeprendtrsviteunecertaineampleur.Lesdeuxproblmesles
pluscourantssontdedterminerlordredanslequellesfichiersetlesbibliothquesdoiventtrecom
pils,ainsiquelesdpendancesentrefichierssourcesetlesfichiersproduitsafindepouvoirregnrer

81

Chapitre6.Modularitdesprogrammesetgnrationdesbinaires
correctementlesfichiersimagesaprsunemodificationdessources.Touscesproblmespeuventtre
rsoluslaidedunprogrammeappelmake.Leprincipedemakeesttoujourslemme,mmesi
aucunenormenatdfinieencequileconcerne.makelitunfichier(lefichier( makefile ),
danslequelsetrouventtouteslesoprationsncessairespourcompilerunprogramme.
Puis, illes
excutesicestncessaire.Parexemple,unfichierquiadjtcompiletquinapastmodifi
depuisneserapasrecompil. Cestplusrapide. makesebasesurlesdatesdederniremodifica
tiondesfichierspoursavoirsilsonttmodifis(ilcomparelesdatesdesfichierssourcesetdes
fichiersproduits).Ladatedesfichiersestgreparlesystmedexploitation:ilestdoncimportant
quelordinateursoitlheure.

6.3.CompilationspareenC/C++
LacompilationspareenC/C++sefaitauniveaudufichier.Ilexistetroisgrandstypesdefichiers
sourcesenC/C++:

lesfichiersdentte,quicontiennenttouteslesdclarationscommunesplusieursfichierssources.
Cesont lesfichiersdenttesqui, ensparant ladclarationdeladfinitiondessymbolesdu
programme,permettentdedcouperlensembledessourcesenfichierscompilablessparment;

lesfichiersC,quicontiennentlesdfinitionsdessymbolesenlangageC;

lesfichiersC++,quicontiennentlesdfinitionsdessymbolesenlangageC++.

OnutiliseuneextensiondiffrentepourlesfichiersCet
lesfichiersC++afindelesdiffrencier.
Lesconventionsutilisesdpendentducompilateur.Cependant,onpeutengnraltablirlesrgles
suivantes:

lesfichiersContlextension .c ;

lesfichiersC++prennentlextension .cc,ou .C (majuscule)surUNIX,ou .cpp surlesPCsous


DOSouWindows(cesdeuxsystmesnefaisantpasladiffrenceentrelesmajusculesetlesmi
nusculesdansleurssystmesdefichiers);

lesfichiersdentteontlextension .h,parfois .hpp (entteC++).

LesprogrammesmodulairesC/C++aurontdonctypiquementlastructuresuivante:

82

Chapitre6.Modularitdesprogrammesetgnrationdesbinaires

Note:Il faudrabienfaireladistinctionentrelesfichierssourcescompilssparment et les


fichiersinclusparleprprocesseur. Cesdernierssont eneffet compilsaveclesfichiersdans
lesquelsilssontinclus.Ilnestdoncpasrecommanddincluredesdfinitionsdesymbolesdans
lesfichiersdentte,carcessymbolesrisquentdapparatredansplusieursfichiersobjetsaprs
lacompilation. Celaprovoquegnralement uneerreurlditiondeliens, parcequelditeur
deliensnepeutpasdterminerquelledfinitionprendreparmi cellesqui setrouventdansles
diffrentsfichiersobjets.

6.4.Syntaxedesoutilsdecompilation
IlexistevidemmentungrandnombredecompilateursC/C++pourchaqueplateforme.Ilsnesont
malheureusementpascompatiblesauniveaudelalignedecommande.Lemmeproblmeapparat
pourlesditeursdeliens(linkerenanglais)etpourmake.Cependant,quelquesprincipesgnraux
peuventtretablis.Danslasuite,jesupposeraiquelenomducompilateurestcc,queceluidu
prprocesseurestcpp,celuidelditeurdeliensestldetqueceluidemakeestmake.
Engnral,lesdiffrentestapesdelacompilationetdelditiondelienssontregroupesauniveau
ducompilateur,cequipermetdefairelesphasesdetraitementduprprocesseur,decompilationet
dditiondeliensenuneseulecommande. Leslignesdecommandesdescompilateurssont donc
souventcompliquesettrspeuportable.Enrevanche,lasyntaxedemake estunpeuplusportable.

6.4.1.Syntaxedescompilateurs
Lecompilateurdemandeengnral lesnomsdesfichierssourcescompileret lesnomsdesfi
chiersobjetsutiliserlorsdelaphasedditiondeliens.Lorsquelonspcifieunfichiersource,le
compilateurutiliseralefichierobjetquilauracrpourcefichiersourceenplusdesfichiersobjets
donnsdanslalignedecommande. Lecompilateurpeut aussi accepterenlignedecommandele

83

Chapitre6.Modularitdesprogrammesetgnrationdesbinaires
cheminderecherchedesbibliothquesdulangageetdesfichiersdentte.Enfin,diffrentesoptions
doptimisationsontdisponibles(maistrspeuportables).Lasyntaxe(simplifie)descompilateursest
souventlasuivante:
cc[fichier.o[...]][[c]fichier.c[...]][oexcutable]
[Lchemin_bibliothques][lbibliothque[...]][Ichemin_include]
fichier.c estlenomdufichiercompiler.Siloption

c leprcde,lefichierseracompil,mais
lditeurdeliensneserapasappel.Sicetteoptionnestpasprsente,lditeurdeliensestappel,
etleprogrammeexcutableformestenregistrdanslefichier a.out.Pourdonnerunautrenom
ceprogramme, ilfaututiliserloption o, suiviedunomdelexcutable. Ilestpossiblededonner
lenomdesfichiersobjetsdjcompils( fichier.o )pourquelditeurdeliensleslieavecle
programmecompil.

Loption L permetdindiquerlechemindurpertoiredesbibliothquesdefonctionsprdfinies.
CerpertoireseraajoutlalistedesrpertoiresindiqusdanslavariabledenvironnementLIBRA
RY_PATH.Loption l demandeaucompilateurdutiliserlabibliothquespcifie,
siellenefait
paspartiedesbibliothquesutilisespardfaut. Demme, loption I permet dedonnerleche
mindaccsaurpertoiredesfichiersinclure(lorsdelutilisationduprprocesseur).Leschemins
ajoutsaveccetteoptionviennentsajouterauxcheminsindiqusdanslesvariablesdenvironnement
C_INCLUDE_PATHetCPLUS_INCLUDE_PATHpourlesprogrammescompilsrespectivementen
CetenC++.
Lordredesparamtressurlalignedecommandeestsignificatif.Lalignedecommandeestexcute
degauchedroite.
Exemple61.Compilationdunfichieretditiondeliens
cccfichier1.c
ccfichier1.oprogramme.ccolancez_moi

Danscet exemple, lefichier C fichier1.c est compilen fichier1.o, puislefichier C++


programme.cc estcompiletliau fichier1.o pourformerlexcutable lancez_moi.

6.4.2.Syntaxedemake
Lasyntaxedemakeesttrssimple:
make

Enrevanche,lasyntaxedufichier makefile estunpeupluscompliqueetpeuportable.Cependant,


lesfonctionnalitsdebasesontgresdelammemanireparlaplupartdesprogrammemake.
Lefichier makefile estconstitudunesriedelignesdinformationetdelignesdecommande(de
linterprteurdecommandesUNIXouDOS).Lescommandesdoiventtoujourstreprcdesdun
caractredetabulationhorizontale.
Leslignesdinformationdonnentdesrenseignementssurlesdpendancesdesfichiers(enparticu
lier, lesfichiersobjetsqui doivent treutilisspourcrerlexcutable). Leslignesdinformation
permettent doncmakedidentifierlesfichierssourcescompilerafindegnrerlexcutable.
Leslignesdecommandeindiquentcommenteffectuercettecompilation(etventuellementdautres
tches).
Lasyntaxedeslignesdinformationestlasuivante:

84

Chapitre6.Modularitdesprogrammesetgnrationdesbinaires
nom:dpendance

o nom estlenomdelacible(gnralement,ilsagitdunomdufichierdestination),et dpendance


estlalistedesnomsdesfichiersdontdpendcettecible, sparspardesespaces. Lasyntaxedes
lignesdecommandeutiliseestcelledelinterprteurdusystmehte.Enfin,lescommentairesdans
unfichiermakefilesefontaveclesignedise(#).
Exemple62.Fichiermakefilesansdpendances
#Compilationdufichierfichier1.c:
cccfichier1.c
#Compilationduprogrammeprincipal:
ccoLancez_moifichier1.oprogramme.c

Exemple63.Fichiermakefileavecdpendances
#Indiquelesdpendances:
Lancez_moi:fichier1.oprogramme.o
#Indiquecommentcompilerleprogramme:
#(lesymbole$@reprsentelenomdelacible,ici,Lancez_moi)
cco$@fichier1.oprogramme.o
#compilelesdpendances:
fichier1.o:fichier1.c
cccfichier1.c
programme.o:programme1.c
cccprogramme.c

6.5.Problmessyntaxiquesrelatifslacompilation
spare
Pourquelecompilateurpuissecompilerlesfichierssparment,ilfautquevousrespectiezlescondi
tionssuivantes:

chaquetypeouvariableutilisdoittredclar;

toutefonctionnondclaredoitrenvoyerunentier(enCseulement, enC++, lutilisationdune


fonctionnondclaregnreuneerreur).

Cesconditionsontdesrpercussionssurlasyntaxedesprogrammes.Ellesserontvuesdanslespara
graphessuivants.

85

Chapitre6.Modularitdesprogrammesetgnrationdesbinaires

6.5.1.Dclarationdestypes
Lestypesdoiventtoujourstredfinisavanttouteutilisationdansunfichiersource.Parexemple,il
estinterditdutiliserunestructureclientsanslavoirdfinieavantsapremireutilisation.Toutefois,il
estpossibledutiliserunpointeursuruntypededonnesanslavoircompltementdfini.Unesimple
dclarationdutypedebasedupointeursuffiteneffetdanscecasl.
Demme, unsimple class
MaClasse suffitenC++pourdclareruneclassesansladfinircompltement.

6.5.2.Dclarationdesvariables
Lesvariablesquisontdfiniesdansunautrefichierdoiventtredclaresavantleurpremireutilisa
tion.Pourcela,onlesspcifiecommetantdesvariablesexternes,aveclemotclextern :
externinti;

/*iestunentierquiestdclaret
crdansunautrefichier.
Ici,ilestsimplementdclar.
*/

Inversement,siunevariablenedoitpastreaccdeparunautremodule,ilfautdclarercettevariable
statique.Ainsi,mmesiunautrefichierutiliselemotcl extern,ilnepourrapasyaccder.

6.5.3.Dclarationdesfonctions
Lorsquunefonctionsetrouvedfiniedansunautrefichier,ilestncessairedeladclarer.Pourcela,
ilsuffitdedonnersadclaration(lemotcl extern estgalementutilisable,maisfacultatifdansce
cas):
intfactorielle(int);
/*
factorielleestunefonctionattendantcommeparamtre
unentieretrenvoyantunevaleurentire.
Elleestdfiniedansunautrefichier.
*/

Lesfonctions inline doiventimprativementtredfiniesdanslesfichiersoellessontutilises,


puisquenthorie, ellessontrecopiesdanslesfonctionsquilesutilisent.
Celaimpliquedeplacer
leurdfinitiondanslesfichiersdentte .h ou .hpp. Commelecodedesfonctions inline est
normalementinclusdanslecodedesfonctionsquilesutilisent,
lesfichiersdenttecontenantdu
code inline peuventtrecompilssparmentsansquecesfonctionsnesoientdfiniesplusieurs
fois. Parconsquent, lditeurdeliensnegnrerapasderreur(alorsquillauraitfaitsionavait
placlecodedunefonctionnon inline dansunfichierdentteinclusdansplusieursfichiers
sources .c ou .cpp).Certainsprogrammeursconsidrentquilnestpasbondeplacerdesdfinitions
inline dansdesfichiers
defonctionsdansdesfichiersdentte,ilplacentdonctoutesleursfonctions
portantlextension .inl.Cesfichierssontensuiteinclussoitdanslesfichiersdentte .h,soitdans
lesfichiers .c ou .cpp quiutilisentlesfonctions inline.

86

Chapitre6.Modularitdesprogrammesetgnrationdesbinaires

6.5.4.Directivesdditiondeliens
LelangageC++donnelapossibilitdappelerdesfonctionsetdutiliserdesvariablesquiproviennent
dunmodulecrit dansunautrelangage. Pourpermettrecela, il disposededirectivespermettant
dindiquercommentlditiondeliensdoittrefaite. Lasyntaxepermettantderalisercelautilise
lemotcl extern,aveclenomdulangageentreguillemets.Cettedirectivedditiondeliensdoit
prcderlesdclarationsdevariablesetdedonnesconcernes.Siplusieursvariablesoufonctions
utilisentlammedirective, ellespeuventtreregroupesdansunblocdlimitpardesaccolades,
avecladirectivedditiondeliensplacejusteavantcebloc.Lasyntaxeestdonclasuivante:
extern"langage"[dclaration|{
dclaration
[...]
}]

Cependant,lesseulslangagesquuneimplmentationdoitobligatoirementsupportersontleslangages
CetC++.Pourlesautreslangages,aucunenormenestdfinieetlesdirectivesdditionde
lienssontdpendantesdelimplmentation.
Exemple64.DclarationsutilisablesenCetenC++
#ifdef__cplusplus
extern"C"
{
#endif
externintEntierC;
intFonctionC(void);
#ifdef__cplusplus
}
#endif

Danslexempleprcdent, lacompilationconditionnelleest utilisepour nutiliser ladirective


dditiondeliensquesi lecodeest compilenC++. Si cest lecas, lavariable EntierC et la
fonction FonctionC sont dclaresaucompilateurC++commetant desobjetsprovenant dun
moduleC.

87

Chapitre6.Modularitdesprogrammesetgnrationdesbinaires

88

Chapitre7.Commentfaireducodeillisible?
Ilestfacile,trsfacile,defairedesprogrammesillisiblesenCouenC++.Ilexistemmeunconcours
ducodeleplusobscur!Celadit,deuxchosespeuventtreditescepropos:

1.anaccrotpaslavitesseduprogramme.Silonveutallerplusvite,ilfautrevoirlalgorithmeou
changerdecompilateur(inutiledefairedelassembleur:lesbonscompilateurssedbrouillent
mieuxquelestrehumainssurceterrain.Lavantagedelassembleurestquel,aumoins,onest
srdavoirunprogrammeillisible.).
2.aaugmenteleschancesdavoirdesbogues.
Sivousvoulezmalgrtoutvousamuser,voiciquelquesconseilsutiles:

crivezdesmacroscomplexesquifontdeseffetsdebordsinsouponnsetquimodifientdesva
riablesglobales;

abusezdeloprateur ternaire ?: et surtout deloprateur virgule ,. Utilisezlesoprateurs


dincrmentation et de dcrmentation outrance, en version prfixe et suffixe, tout
spcialementdansdesexpressionsutilisantdespointeurs;

placezcesoprateursdanslesstructuresdecontrles.Notamment,utilisezloprateurvirgulepour
fairedesinstructionscomposesdanslestestsdu while etdanstouslesmembresdu for.Ilest
souventpossibledemettrelecorpsdu for danslesparenthses;

sincessaire,utiliserlesexpressionscomposes(

choisissezdesnomsdevariableetdefonctionalatoires(pensezunephrase,etprenezlespre
miresoulesdeuximeslettresdesmotsauhasard);

regroupeztouteslesfonctionsdansunmmefichier,parordredenonappariement;

inversement, dispersezlesdfinitionsdesvariablesglobalesdanstoutleprogramme, sipossible


dansdesfichiersoellesnesontpasutilises;

faitesdesfonctionsrallonge;

ne soignez pas lapparence de votre programme (pas dindentationou, aucontraire, trop


dindentations),regroupezplusieursinstructionssurunemmeligne;

rajoutezdesparenthsesloellesnesontpasncessaires;

rajoutezdestranstypagesloilsnesontpasncessaires;

necommentezrien,oumieux,donnezdescommentairessansrapportaveclecode.

{ et })danslesstructuresdecontrle;

Exemple71.Programmeparfaitementillisible
/*Quefaitceprogramme?*/
#include <stdio.h>
intmain(void)
{
intzkmlpf,geikgh,wdxaj;
scanf("%u",&zkmlpf);for(wdxaj=0,
geikgh=0;

89

Chapitre7.Commentfaireducodeillisible?
((wdxaj+=++geikgh),geikgh)
<zkmlpf;);
printf("%u",wdxaj);return0;
}

Vouslaurezcompris:ilestplussimplededireicicequilnefautpasfairequededirecommentil
fautfaire.Jeneprtendspasimposerquiconqueunemthodologiequelconque,carchacunestlibre
deprogrammercommeillentend. Eneffet, certainesconventionsdecodagessontaussiabsurdes
quinutilesetellesontlinconvnientdeneplairequceluiquilesacrites(etencore...).Cestpour
cetteraisonquejemesuiscontentdelisterlessourcespotentiellesdillisibilitdesprogrammes.
Sachezdoncsimplementquesivousutilisezunedestechniquesdonnesdansceparagraphe,vous
devriezvousassurerquecestrellementjustifietrevoirvotrecode.Pourobtenirdesprogrammes
lisibles,ilfautsimplementquechacunymettreunpeudusien,cestaussiunemarquedepolitesse
enverslesautresprogrammeurs.

90

Chapitre8.C++:lacoucheobjet
Lacoucheobjet constituesansdoutelaplusgrandeinnovationduC++parrapport
auC. Lebut
delaprogrammationobjetestdepermettreuneabstractionentrelimplmentationdesmoduleset
leurutilisation, apportant ainsi unplusgrandconfort danslaprogrammation. Ellesintgredonc
parfaitementdanslecadredelamodularit.Enfin,lencapsulationdesdonnespermetunemeilleure
protectionetdoncuneplusgrandefiabilitdesprogrammes.

8.1.Gnralits
Thoriquement, ilyaunenettedistinctionentrelesdonnesetlesoprationsquileursontappli
ques.Entoutcas,lesdonnesetlecodenesemlangentpasdanslammoiredelordinateur,sauf
castrsparticuliers(autoprogrammation,aliaspourlechargementdesprogrammesoudesoverlays,
dbogueurs,virus).
Cependant,lanalysedesproblmestraiterseprsentedunemanireplusnaturellesilonconsidre
lesdonnesavecleursproprits.Lesdonnesconstituentlesvariables,etlespropritslesoprations
quonpeutleurappliquer.Decepointdevue,lesdonnesetlecodesontlogiquementinsparables,
mmesilssontplacsendiffrentsendroitsdelammoiredelordinateur.
Cesconsidrationsconduisentlanotiondobjet.Unobjetestunensemblededonnessurlesquelles
desprocdurespeuventtreappliques. Cesprocduresoufonctionsapplicablesauxdonnessont
appelesmthodes.Laprogrammationdunobjetsefaitdoncenindiquantlesdonnesdelobjetet
endfinissantlesprocduresquipeuventluitreappliques.
Ilsepeutquilyaitplusieursobjetsidentiques,dontlesdonnesontbienentendudesvaleursdiff
rentes,maisquiutilisentlemmejeudemthodes.Onditquecesdiffrentsobjetsappartiennent
lammeclassedobjets.Uneclasseconstituedoncunesortedetype,etlesobjetsdecetteclasseen
sontdesinstances.Laclassedfinitdonclastructuredesdonnes,alorsappeleschampsouvariables
dinstances,quelesobjetscorrespondantsauront,ainsiquelesmthodesdelobjet.chaqueinstan
ciation,uneallocationdemmoireestfaitepourlesdonnesdunouvelobjetcr.Linitialisationde
lobjetnouvellementcrestfaiteparunemthodespciale,leconstructeur.Lorsquelobjetestd
truit,uneautremthodeestappele:ledestructeur.Lutilisateurpeutdfinirsespropresconstructeurs
etdestructeursdobjetssincessaire.
Commeseuleslesvaleursdesdonnesdesdiffrentsobjetsduneclassediffrent,lesmthodessont
misesencommunpourtouslesobjetsdunemmeclasse(cestdirequelesmthodesnesontpas
recopies).Pourquelesmthodesappelespourunobjetsachentsurquellesdonnesellesdoivent
travailler,unpointeursurlobjetcontenantcesdonnesleurestpassenparamtre.Cemcanisme
estcompltementtransparentpourleprogrammeurenC++.
Nousvoyonsdoncquenonseulementlaprogrammationorienteobjetestpluslogique,maiselleest
galementplusefficace(lesmthodessontmisesencommun,lesdonnessontspares).
Enfin,lesdonnesdesobjetspeuventtreprotges:cestdirequeseuleslesmthodesdelobjet
peuventyaccder.Cenestpasuneobligation,maiscelaaccrotlafiabilitdesprogrammes.Siune
erreurseproduit,seuleslesmthodesdelobjetdoiventtrevrifies.Deplus,lesmthodesconsti
tuentainsiuneinterfaceentrelesdonnesdelobjetetlutilisateurdelobjet(unautreprogrammeur).
Cetutilisateurnadoncpassavoircommentlesdonnessontgresdanslobjet,ilnedoitutiliser
quelesmthodes.Lesavantagessontimmdiats:ilnerisquepasdefairedeserreursdeprogramma
tionenmodifiantlesdonnesluimme,lobjetestrutilisabledansunautreprogrammeparcequila
uneinterfacestandardise,etonpeutmodifierlimplmentationinternedelobjetsansavoirrefaire
toutleprogramme,pourvuquelesmthodesgardentlemmenom,lesmmesparamtresetlamme

91

Chapitre8.C++:lacoucheobjet
smantique.Cettenotiondeprotectiondesdonnesetdemasquagedelimplmentationinterneaux
utilisateursdelobjetconstituecequelonappellelencapsulation.Lesavantagesdelencapsulation
serontsouventmisenvaleurdanslasuiteautraversdexemples.
Nousallonsentrermaintenantdanslevifdusujet.Celapermettradecomprendrecesgnralits.

8.2.ExtensiondelanotiondetypeduC
IlfautavanttoutsavoirquelacoucheobjetnestpasunsimpleajoutaulangageC,cestunevritable
extension. Eneffet, lesnotionsquelleaapportesonttintgresauCtelpointqueletypage
desdonnesdeCafusionnaveclanotiondeclasse.Ainsi,lestypesprdfinischar,int,double,etc.
reprsententprsentlensembledespropritsdesvariablesayantcetype.Cespropritsconstituent
laclassedecesvariables,etellessontaccessiblesparlesoprateurs.Parexemple,ladditionestune
oprationpouvantportersurdesentiers(entreautres)quirenvoieunobjetdelaclasseentier.
Par
consquent, lestypesdebasesemanipulerontexactementcommedesobjets. Dupointdevuedu
C++,lesutiliserrevientdjfairedelaprogrammationorienteobjet.
Demme,leprogrammeurpeut,laidedelanotiondeclassedobjets,dfinirdenouveauxtypes.Ces
typescomprennentlastructuredesdonnesreprsentesparcestypesetlesoprationsquipeuvent
leurtreappliques.Enfait,leC++assimilecompltementlesclassesaveclestypes,etladfinition
dunnouveautypesefaitdoncendfinissantlaclassedesvariablesdecetype.

8.3.DclarationdeclassesenC++
Afindepermettreladfinitiondesmthodesquipeuventtreappliquesauxstructuresdesclasses
C++, lasyntaxedesstructuresCattendue(et
simplifie). Il est prsent possiblededfinir
compltementdesmthodesdansladfinitiondelastructure.Cependantilestprfrabledelareporter
etdenelaisserqueleurdclarationdanslastructure.Eneffet,celaaccrotlalisibilitetpermetde
masquerlimplmentationdelaclassesesutilisateursenneleurmontrantquesadclarationdans
unfichierdentte.Ilsnepeuventdoncnilavoir,nilamodifier(enrevanche,ilspeuventtoujours
voirlastructurededonnesutiliseparsonimplmentation).
Lasyntaxeestlasuivante:
structNom
{
[typechamps;
[typechamps;
[...]]]
[mthode;
[mthode;
[...]]]
};

o Nom estlenomdelaclasse.Ellepeutcontenirdiverschampsdediverstypes.
Lesmthodespeuvent tredesdfinitionsdefonctions, ouseulement leursdclarations. Si onne
donnequeleursdclarations,ondevralesdfinirplusloin.Pourcela,ilfaudraspcifierlaclasse
laquelleellesappartiennentaveclasyntaxesuivante:
typeclasse::nom(paramtres)
{

92

Chapitre8.C++:lacoucheobjet
/*Dfinitiondelamthode.*/
}

Lasyntaxeestdoncidentiqueladfinitiondunefonctionnormale,
ladiffrenceprsqueleur
nomestprcddunomdelaclasselaquelleellesappartiennentetdedeuxdeuxpoints( ::).Cet
oprateur :: estappelloprateurdersolutiondeporte. Ilpermet, dunemaniregnrale, de
spcifierleblocauquellobjetquilesuitappartient.Ainsi,lefaitdeprcderlenomdelamthode
parlenomdelaclassepermetaucompilateurdesavoirdequelleclassecettemthodefaitpartie.
Rienninterdit, eneffet, davoirdesmthodesdemmesignature, pourvuquellessoientdansdes
classesdiffrentes.
Exemple81.Dclarationdemthodesdeclasse
structEntier
{
inti;

//Donnemembredetypeentier.

//Fonctiondfinielintrieurdelaclasse:
intlit_i(void)
{
returni;
}
//Fonctiondfinielextrieurdelaclasse:
voidecrit_i(intvaleur);
};
voidEntier::ecrit_i(intvaleur)
{
i=valeur;
return;
}
Note:Si lalistedesparamtresdeladfinitiondelafonctioncontient desinitialisationssup
plmentairescellesqui ont tspcifiesdansladclarationdelafonction, lesdeuxjeux
dinitialisationssontfusionnesetutilisesdanslefichieroladfinitiondelafonctionestplace.
Silesinitialisationssontredondantesoucontradictoires,lecompilateurgnreuneerreur.

Note:Loprateurdersolutiondeportepermet aussi despcifierleblocdinstructionsdun


objet qui nappartient aucuneclasse. Pourcela, onnemettraaucunnomavant
loprateur
dersolutiondeporte. Ainsi, pouraccderunefonctionglobalelintrieur duneclasse
contenantunefonctiondemmesignature,onferaprcderlenomdelafonctionglobaledecet
oprateur.
Exemple82.Oprateurdersolutiondeporte
intvaleur(void)
{
return0;
}

//Fonctionglobale.

structA
{

93

Chapitre8.C++:lacoucheobjet
inti;
voidfixe(inta)
{
i=a;
return;
}
intvaleur(void)
{
returni;
}

//Mmesignaturequelafonctionglobale.

intglobal_valeur(void)
{
return::valeur();//Accdelafonctionglobale.
}
};

Demme, loprateur dersolutiondeportepermettradaccder unevariableglobale


lorsquuneautrevariablehomonymeauratdfiniedansleblocencours.Parexemple:
inti=1;
intmain(void)
{
if(test())
{
inti=3;
intj=2*::i;
/*Suite...*/
}

//Premirevariabledeporteglobale

//Variablehomonymedeportelocale.
//jvautprsent2,etnonpas6.

/*Suite...*/
return0;
}

Leschampsduneclassepeuventtreaccdscommedesvariablesnormalesdanslesmthodesde
cetteclasse.
Exemple83.Utilisationdeschampsduneclassedansunedesesmthodes
structclient
{
charNom[21],Prenom[21];
unsignedintDate_Entree;

//Dfinitleclient.
//Datedentreduclient
//danslabasededonnes.

intSolde;
booldans_le_rouge(void)
{
return(Solde<0);
}
boolbon_client(void)

94

//Lebonclientest

Chapitre8.C++:lacoucheobjet
//unancienclient.
{
return(Date_Entree<1993);//Datelimite:1993.
}
};

Danscetexemple,leclientestdfiniparcertainesdonnes.Plusieursmthodessontdfiniesdansla
classemme.
Linstanciationdunobjetsefaitcommecelledunesimplevariable:
classeobjet;

Parexemple,sionaunebasededonnesdevantcontenir100clients,onpeutfaire:
clientclientele[100];

/*Instancie100clients.*/

Onremarqueraquil est prsent inutiledutiliserlemot cl struct pourdclarerunevariable,


contrairementcequelasyntaxeduCexigeait.
Laccsauxmthodesdelaclassesefaitcommepouraccderauxchampsdesstructures.Ondonne
lenomdelobjetetlenomduchampoudelamthode,sparsparunpoint.Parexemple:
/*Relancedetouslesmauvaispayeurs.*/
inti;
for(i=0;i <100;++i)
if(clientele[i].dans_le_rouge())relance(clientele[i]);

Lorsquelesfonctionsmembresduneclassesontdfiniesdansladclarationdecetteclasse,lecom
pilateurlesimplmenteen inline (moinsquellesnesoientrcursivesouquilexisteunpointeur
surelles).
Si lesmthodesnesont pasdfiniesdanslaclasse, ladclarationdelaclasseseramisedansun
fichierdentte, etladfinitiondesmthodesserareportedansunfichierC++,
quiseracompil
etliauxautresfichiersutilisantlaclasseclient.
Bienentendu, ilesttoujourspossiblededclarer
lesfonctionsmembrescommetantdesfonctions inline mmelorsquellessontdfiniesendehors
deladclarationdelaclasse.Pourcela,ilfaututiliserlemotcl inline,etplacerlecodedeces
fonctionsdanslefichierdentteoudansunfichier.inl.
Sansfonctionsinline,notreexempledevient:
Fichierclient.h:
structclient
{
charNom[21],Prenom[21];
unsignedintDate_Entree;
intSolde;
booldans_le_rouge(void);
boolbon_client(void);
};

95

Chapitre8.C++:lacoucheobjet
/*
Attentionnepasoublierle;lafindelaclassedansun
fichier.h!Lerreurapparatraitdanstouslesfichiersayant
uneligne#include"client.h",parcequelacompilationalieu
aprslappelauprprocesseur.
*/

Fichierclient.cc:
/*Inclutladclarationdelaclasse:*/
#include"client.h"
/*Dfinitlesmthodesdelaclasse:*/
boolclient::dans_le_rouge(void)
{
return(Solde<0);
}
boolclient::bon_client(void)
{
return(Date_Entree<1993);
}

8.4.Encapsulationdesdonnes
Lesdiverschampsdunestructuresontaccessiblesennimportequelendroitduprogramme.
oprationtellequecelleciestdoncfaisable:

Une

clientele[0].Solde=25000;

Lesoldedunclientpeutdonctremodifisanspasserparunemthodedontceseraitlebut.Elle
pourraitparexemplevrifierquelonnaffectepasunsoldesuprieurausoldemaximalautorispar
leprogramme(labornesuprieuredesvaleursdesentierssigns).
Parexemple, silesentierssont
codssur16bits,cettebornemaximumest32767.Unprogrammequiferait:
clientele[0].Solde=32800;

obtiendraitdoncunsoldede12(valeurennombresigndunombrenonsign32800),alorsquil
espreraitobtenirunsoldepositif!
Ilestpossibledempcherlaccsdeschampsoudecertainesmthodestoutefonctionautreque
cellesdelaclasse.Cetteoprationsappellelencapsulation.Pourlaraliser,ilfaututiliserlesmots
clssuivants:
public

:lesaccssontlibres;

private

96

:lesaccssontautorissdanslesfonctionsdelaclasseseulement;

Chapitre8.C++:lacoucheobjet
:lesaccssontautorissdanslesfonctionsdelaclasseetdesesdescendantes(voir
lasectionsuivante)seulement.Lemotcl protected nestutilisquedanslecadredelhritage
desclasses.Lasectionsuivantedtailleracepoint.

protected

Pourchangerlesdroitsdaccsdeschampsetdesmthodesduneclasse,ilfautfaireprcderceux
:).Parexemple,pourprotgerles
cidumotclindiquantlesdroitsdaccssuividedeuxpoints(
donnesrelativesauclient,onchangerasimplementladclarationdelaclasseen:
structclient
{
private:
//Donnesprives:
charNom[21],Prenom[21];
unsignedintDate_Entree;
intSolde;
//Ilnyapasdemthodeprive.
public:

//Lesdonnesetlesmthodespubliques:

//Ilnyapasdedonnepublique.
booldans_le_rouge(void);
boolbon_client(void)
};

Outrelavrificationdelavaliditdesoprations, lencapsulationacommeintrtfondamentalde
dfiniruneinterfacestablepourlaclasseauniveaudesmthodesetdonnesmembrespubliqueset
protges.Limplmentationdecetteinterface,raliseenpriv,peuttremodifieloisirsanspour
autantperturberlesutilisateursdecetteclasse,tantquecetteinterfacenestpasellemmemodifie.
Pardfaut, lesclassesconstruitesavec struct onttousleursmembrespublics. Ilestpossiblede
dclareruneclassedonttousleslmentssontpardfautprivs.Pourcela,ilsuffitdutiliserlemot
cl class laplacedumotcl struct.
Exemple84.Utilisationdumotclclass
classclient
{
//privateestprsentinutile.
charNom[21],Prenom[21];
unsignedintDate_Entree;
intSolde;
public:

//Lesdonnesetlesmthodespubliques.

booldans_le_rouge(void);
boolbon_client(void);
};

Enfin,ilexisteunderniertypedeclasse,quejemecontenteraidementionner:lesclassesunion.Elles
sedclarentcommelesclasses struct et class, maisaveclemotcl union. Lesdonnessont,
commepourlesunionsduC,situestoutesaummeemplacement,cequifaitqucriredanslune

97

Chapitre8.C++:lacoucheobjet
dentreelleprovoqueladestructiondesautres.Lesunionssonttrssouventutilisesenprogramma
tionsystme,lorsquunpolymorphismephysiquedesdonnesestncessaire(cestdirelorsquelles
doiventtreinterprtesdediffrentesfaonsselonlecontexte).
Note:Lesclassesdetype union nepeuventpasavoirdemthodesvirtuellesetdemembres
statiques.Ellesnepeuventpasavoirdeclassesdebase,ni servirdeclassedebase.Enfin,les
unionsnepeuventpascontenirdesrfrences,nidesobjetsdontlaclasseaunconstructeurnon
trivial,unconstructeurdecopienontrivial
ouundestructeurnontrivial.Pourtoutescesnotions,
voirlasuiteduchapitre.
Lesclassesdfiniesauseinduneautreclassesontconsidrescommefaisantpartiedeleur
private et protected decelle
classehte,etontdoncledroitdaccderauxdonnesmembres
ci.Remarquezquecettergleestassezrcentedanslanormedulangage,etquelaplupartdes
compilateursrefuserontcesaccs.Il faudradoncdclareramiesdelaclassehtelesclasses
quisontdfiniesauseindecelleci.LamaniredeprocderseradcritedanslaSection8.7.2.

8.5.Hritage
Lhritagepermet dedonneruneclassetouteslescaractristiquesduneoudeplusieursautres
classes.Lesclassesdontellehritesontappelesclassesmres,classesdebaseouclassesantc
dentes.Laclasseellemmeestappeleclassefille,classedriveouclassedescendante.
Lespropritshritessontleschampsetlesmthodesdesclassesdebase.
PourfaireunhritageenC++,ilfautfairesuivrelenomdelaclassefilleparlalistedesclassesmres
dansladclarationaveclesrestrictionsdaccsauxdonnes,chaquelmenttantspardesautres
parunevirgule.Lasyntaxe(donnepour class,identiquepour struct)estlasuivante:
classClasse_mere1
{
/*Contenudelaclassemre1.*/
};
[classClasse_mere2
{
/*Contenudelaclassemre2.*/
};]
[...]
classClasse_fille:public|protected|privateClasse_mere1
[,public|protected|privateClasse_mere2[...]]
{
/*Dfinitiondelaclassefille.*/
};

Danscettesyntaxe, Classe_fille hritedela Classe_mere1,etdes Classe_mere2,etc.sielles


sontprsentes.
Lasignificationdesmotscls private, protected et public danslhritageestrcapituledans
letableausuivant:

98

Chapitre8.C++:lacoucheobjet
Tableau81.Droitsdaccssurlesmembreshrits
motclutilispourlhritage
Accsauxdonnes
motclutilis

public

protected

private

public

public

protected

private

pourleschamps

protected

protected

protected

private

etlesmthodes

private

interdit

interdit

interdit

Ainsi,lesdonnespubliquesduneclassemredeviennentsoitpubliques,soitprotges,soitprives
selonquelaclassefillehriteenpublic,protgouenpriv.Lesdonnesprivesdelaclassemre
sonttoujoursinaccessibles,etlesdonnesprotgesdeviennentsoitprotges,soitprives.
Ilestpossibledomettrelesmotsclspublic, protected et private danslasyntaxedelhritage.
Lecompilateurutiliseuntypedhritagepardfautdanscecas.Lesclassesdetypestruct utilisent
lhritage public pardfautetlesclassesdetype class utilisentlemotcl private pardfaut.
Exemple85.Hritagepublic,privetprotg
classEmplacement
{
protected:
intx,y;

//Donnesnepouvanttreaccdes
//queparlesclassesfilles.

public:
voidChange(int,int);//Mthodetoujoursaccessible.
};
voidEmplacement::Change(inti,intj)
{
x=i;
y=j;
return;
}
classPoint:publicEmplacement
{
protected:
unsignedintcouleur; //Donneaccessible
//auxclassesfilles.
public:
voidSetColor(unsignedint);
};
voidPoint::SetColor(unsignedintNewColor)
{
couleur=NewColor;
//Dfinitlacouleur.
return;
}

SiuneclasseCercledoithriterdedeuxclassesmres,parexempleEmplacementetForme,sad
clarationauralaformesuivante:

99

Chapitre8.C++:lacoucheobjet
classCercle:publicEmplacement,publicForme
{
/*
DfinitiondelaclasseCercle.Cetteclassehrite
desdonnespubliquesetprotgesdesclassesEmplacement
etForme.
*/
};

Ilestpossiblederedfinirlesfonctionsetlesdonnesdesclassesdebasedansuneclassedrive.
Parexemple,siuneclasseBdrivedelaclasseA,etquetoutesdeuxcontiennentunedonne d,les
instancesdelaclasseButiliserontladonned delaclasseBetlesinstancesdelaclasseAutiliseront
ladonne d delaclasseA.Cependant,lesobjetsdeclasseBcontiendrontgalementunsousobjet,
luimmeinstancedelaclassedebaseA.Parconsquent,ilscontiendrontladonne
d delaclasseA,
maiscettedernireseracacheparladonne d delaclasselaplusdrive,savoirlaclasseB.
Cemcanismeestgnral:quanduneclassedriveredfinitunmembreduneclassedebase,ce
membreestcachetonnepeutplusaccderdirectementquaumembreredfini(celuidelaclasse
drive).Cependant,ilestpossibledaccderauxdonnescachessilonconnatleurclasse,pour
cela, ilfautnommerlemembrecompltementlaidedeloprateurdersolutiondeporte( ::).
Lenomcompletdunmembreestconstitudunomdesaclassesuivideloprateurdersolutionde
porte,suivisdunomdumembre:
classe::membre

Exemple86.Oprateurdersolutiondeporteetmembredeclassesdebase
structBase
{
inti;
};
structDerivee:publicBase
{
inti;
intLitBase(void);
};
intDerivee::LitBase(void)
{
returnBase::i;//Renvoielavaleuridelaclassedebase.
}
intmain(void)
{
DeriveeD;
D.i=1;
D.Base::i=2;
return0;
}

100

//AccdelentieridelaclasseDerivee.
//AccdelentieridelaclasseBase.

Chapitre8.C++:lacoucheobjet

8.6.Classesvirtuelles
SupposonsprsentquuneclasseDhritededeuxclassesmres,
lesclassesBetC. Supposons
galementquecesdeuxclasseshritentduneclassemrecommuneappeleclasseA.Onalarbre
gnalogiquesuivant:

OnsaitqueBetChritentdesdonnesetdesmthodespubliquesetprotgesdeA.Demme,D
hritedesdonnesdeBetC,etparleurintermdiairedesdonnesdeA.Ilseposedoncleproblme
suivant:quellessontlesdonnesquelondoitutiliserquandonrfrenceleschampsdeA?Celles
deBoucellesdeC?OnpeutaccderauxdeuxsousobjetsdeclasseAenspcifiantlechemin
suivredanslarbregnalogiquelaidedeloprateurdersolutiondeporte.Cependant,celanest
nipratiqueniefficace,etengnral,onsattendcequuneseulecopiedeAapparaissedansD.
Leproblmeest rsoluendclarant virtuellelaclassedebasecommunedanslaspcificationde
lhritagepourlesclassesfilles. Lesdonnesdelaclassedebaseneserontalorsplusdupliques.
Pourdclareruneclassemrecommeuneclassevirtuelle,ilfautfaireprcdersonnomdumotcl
virtual danslhritagedesclassesfilles.
Exemple87.Classesvirtuelles
classA
{
protected:
intDonnee;
};

//Ladonnedelaclassedebase.

//HritagedelaclasseA,virtuelle:
classB:virtualpublicA
{
protected:
intValeur_B;
//Autredonneque"Donnee"(hrite).
};
//Aesttoujoursvirtuelle:
classC:virtualpublicA
{

101

Chapitre8.C++:lacoucheobjet
protected:
intvaleur_C;

//Autredonne
//("Donnee"estacquiseparhritage).

};
classD:publicB,publicC
//Ici,Donneenestpasdupliqu.
{
/*DfinitiondelaclasseD.*/
};
Note:Normalement,lhritageestralisparlecompilateurparaggrgationdelastructurede
donnesdesclassesdebasedanslastructurededonnesdelaclassedrive.Pourlesclasses
virtuelles,cenestengnralpaslecas,puisquelecompilateurdoitassurerlunicitdesdonnes
hritesdecesclasses,mmeencasdhritagemultiple.Parconsquent,certainesrestrictions
dusagesappliquentsurlesclassesvirtuelles.
Premirement,il estimpossibledetranstyperdirectementunpointeursurunobjetduneclasse
debasevirtuelleenunpointeursurunobjetdunedesesclassesdrives.Ilfautimprativement
utiliserloprateurdetranstypagedynamique dynamic_cast .Cetoprateurseradcritdansle
Chapitre10.
Deuximement,chaqueclassedrivedirectementouindirectementduneclassevirtuelledoit
enappelerleconstructeurexplicitementdanssonconstructeursiceluiciprenddesparamtres.
Eneffet,ellenepeutpassefieraufaitquuneautredesesclassesdebase,ellemmedrive
delaclassedebasevirtuelle,appelleunconstructeurspcifique,carilestpossiblequeplusieurs
classesdebasecherchentinitialiserdiffremmentchacuneunobjetcommunhritdelaclasse
virtuelle.Pourreprendrelexempledonncidessus,silesclassesBetCappellaienttoutesles
deuxunconstructeurnontrivialdelaclassevirtuelleA,etquelaclasseDappellaitellemme
lesconstructeursdeBetC,lesousobjethritdeAseraitconstruitplusieursfois.Pourviter
cela,lecompilateurignorepurementetsimplementlesappelsauconstructeurdesclassesde
basesvirtuellesdanslesclassesdebasedrives.Ilfautdoncsystmatiquementlespcifier,
chaqueniveaudelahirarchiedeclasse.LanotiondeconstructeurseravuedanslaSection8.8

8.7.Fonctionsetclassesamies
Ilestparfoisncessairedavoirdesfonctionsquiontunaccsillimitauxchampsduneclasse.En
gnral,lemploidetellesfonctionstraduitunmanquedanalysedanslahirarchiedesclasses,mais
pastoujours.Ellesrestentdoncncessairesmalgrtout.
Detellesfonctionssontappelesdesfonctionsamies.Pourquunefonctionsoitamieduneclasse,il
fautquellesoitdclaredanslaclasseaveclemotcl friend.
Ilestgalementpossibledefaireuneclasseamieduneautreclasse,maisdanscecas,cetteclasse
devraitpeuttretreuneclassefille.Lutilisationdesclassesamiespeuttraduireundfautdeconcep
tion.

8.7.1.Fonctionsamies
Lesfonctionsamiessedclarentenfaisantprcderladclarationclassiquedelafonctiondumotcl
friend lintrieurdeladclarationdelaclassecible.Lesfonctionsamiesnesontpasdesmthodes
delaclassecependant(celanauraitpasdesenspuisquelesmthodesontdjaccsauxmembresde
laclasse).

102

Chapitre8.C++:lacoucheobjet
Exemple88.Fonctionsamies
classA
{
inta;
friendvoidecrit_a(inti);
};

//Unedonneprive.
//Unefonctionamie.

Aessai;
voidecrit_a(inti)
{
essai.a=i;
return;
}

//Initialisea.

Ilestpossiblededclareramieunefonctionduneautreclasse,enprcisantsonnomcompletlaide
deloprateurdersolutiondeporte.

8.7.2.Classesamies
Pourrendretouteslesmthodesduneclasseamiesduneautreclasse,ilsuffitdedclarerlaclasse
compltecommetantamie. Pourcela, ilfautencoreunefoisutiliserlemotcl friend avantla
dclarationdelaclasse,lintrieurdelaclassecible.Cettefoisencore,laclasseamiedclarene
serapasunesousclassedelaclassecible,maisbienuneclassedeporteglobale.
Note:Lefait,pouruneclasse,dapparteniruneautreclasselui donneledroitdaccderaux
membresdesaclassehte. Il nest doncpasncessairededclareramiesduneclasseles
classesdfiniesauseindecelleci.Remarquezquecettergleatrcemmentmodifiedans
lanormeC++,etquelaplupartdescompilateursrefuserontauxclassesinclusesdaccderaux
membresnonpublicsdeleurconteneur.

Exemple89.Classeamie
#include <stdio.h>
classHote
{
friendclassAmie;
inti;

//TouteslesmthodesdeAmiesontamies.
//DonneprivedelaclasseHote.

public:
Hote(void)
{
i=0;
return;
}
};
Hoteh;
classAmie

103

Chapitre8.C++:lacoucheobjet
{
public:
voidprint_hote(void)
{
printf("%d\n",h.i);//Accdeladonneprivedeh.
return;
}
};
intmain(void)
{
Amiea;
a.print_hote();
return0;
}

Onremarqueraplusieurschosesimportantes.Premirement,lamitinestpastransitive.Celasignifie
quelesamisdesamisnesontpasdesamis.UneclasseAamieduneclasseB,ellemmeamiedune
classeC,nestpasamiedelaclasseCpardfaut.Ilfautladclareramieexplicitementsiondsire
quellelesoit. Deuximement, lesamisnesontpashrits. Ainsi, siuneclasseAestamiedune
classeBetquelaclasseCestuneclassefilledelaclasseB,alorsAnestpasamiedelaclasseCpar
dfaut.Encoreunefois,ilfautladclareramieexplicitement.Cesremarquessappliquentgalement
auxfonctionsamies(unefonctionamieduneclasseAamieduneclasseBnestpasamiedelaclasse
B,nidesclassesdrivesdeA).

8.8.Constructeursetdestructeurs
Leconstructeuretledestructeursontdeuxmthodesparticuliresquisontappelesrespectivement
lacrationetladestructiondunobjet.Touteclasseaunconstructeuretundestructeurpardfaut,
fournisparlecompilateur.Cesconstructeursetdestructeursappellentlesconstructeurspardfautet
lesdestructeursdesclassesdebaseetdesdonnesmembresdelaclasse,maisendehorsdecela,ils
nefontabsolumentrien.Ilestdoncsouventncessairedelesredfinirafindegrercertainesactions
quidoiventavoirlieulorsdelacrationdunobjetetdeleurdestruction.Parexemple,silobjetdoit
contenirdesvariablesallouesdynamiquement,ilfautleurrserverdelammoirelacrationde
lobjetouaumoinsmettrelespointeurscorrespondantsNULL.ladestructiondelobjet,ilconvient
derestituerlammoirealloue,silenatallou.Onpeuttrouverbiendautressituationsoune
phasedinitialisationetunephasedeterminaisonsontncessaires.
Dsquunconstructeur ouundestructeur atdfini par lutilisateur, lecompilateur nedfinit
plusautomatiquementleconstructeurouledestructeurpardfautcorrespondant.
Enparticulier, si
lutilisateurdfinitunconstructeurprenantdesparamtres,ilneserapluspossibledeconstruireun
objetsimplement,sansfournirlesparamtresceconstructeur,moinsbienentendudedfinirga
lementunconstructeurquineprennepasdeparamtres.

8.8.1.Dfinitiondesconstructeursetdesdestructeurs
Leconstructeursedfinitcommeunemthodenormale.Cependant,pourquelecompilateurpuisse
lareconnatreentantqueconstructeur,lesdeuxconditionssuivantesdoiventtrevrifies:

104

elledoitporterlemmenomquelaclasse;

Chapitre8.C++:lacoucheobjet

ellenedoitavoiraucuntype,pasmmeletypevoid.

Ledestructeurdoitgalementrespectercesrgles.Pourlediffrencierduconstructeur,sonnomsera
toujoursprcddusignetilde(~).
Unconstructeurestappelautomatiquementlorsdelinstanciationdelobjet.Ledestructeurestap
pelautomatiquement lorsdesadestruction. Cettedestructionalieulorsdelasortiedublocde
portecourantepourlesobjetsdeclassedestockage auto.Pourlesobjetsallousdynamiquement,
leconstructeuretledestructeursontappelsautomatiquementparlesexpressionsquiutilisentles
oprateurs new, new[], delete et delete[].Cestpourcelaquilestrecommanddelesutiliser
laplacedesfonctions malloc et free duCpourcrerdynamiquementdesobjets.Deplus,ilne
fautpasutiliser delete ou delete[] surdespointeursdetypevoid,carilnexistepasdobjetsde
typevoid.Lecompilateurnepeutdoncpasdterminerquelestledestructeurappeleraveccetype
depointeur.
Leconstructeurestappelaprslallocationdelammoiredelobjetetledestructeurestappelavant
lalibrationdecettemmoire.Lagestiondelallocationdynamiquedemmoireaveclesclassesest
ainsisimplifie.Danslecasdestableaux,lordredeconstructionestceluidesadressescroissantes,et
lordrededestructionestceluidesadressesdcroissantes.Cestdanscetordrequelesconstructeurs
etdestructeursdechaquelmentdutableausontappels.
Lesconstructeurspourrontavoirdesparamtres.Ilspeuventdonctresurchargs,maispaslesdes
tructeurs.Celaestdafaitquengnralonconnatlecontextedanslequelunobjetestcr,mais
quonnepeutpasconnatrelecontextedanslequelilestdtruit:ilnepeutdoncyavoirquunseul
destructeur.Lesconstructeursquineprennentpasdeparamtreoudonttouslesparamtresontune
valeurpardfaut,remplacentautomatiquementlesconstructeurspardfautdfinisparlecompilateur
lorsquilnyaaucunconstructeurdanslesclasses.
Celasignifiequecesontcesconstructeursqui
serontappelsautomatiquementparlesconstructeurspardfautdesclassesdrives.
Exemple810.Constructeursetdestructeurs
classchaine
{
char*s;

//Implmenteunechanedecaractres.
//Lepointeursurlachanedecaractres.

public:
chaine(void);
chaine(unsignedint);
~chaine(void);
};
chaine::chaine(void)
{
s=NULL;
return;
}

//Leconstructeurpardfaut.
//Leconstructeur.Ilnapasdetype.
//Ledestructeur.

//Lachaneestinitialiseavec
//lepointeurnul.

chaine::chaine(unsignedintTaille)
{
s=newchar[Taille+1];//Allouedelammoirepourlachane.
s[0]=\0;
//Initialiselachane"".
return;
}
chaine::~chaine(void)

105

Chapitre8.C++:lacoucheobjet
{
if(s!=NULL)delete[]s;//Restituelammoireutilisesi
//ncessaire.
return;
}

Pourpasserlesparamtresauconstructeur,ondonnelalistedesparamtresentreparenthsesjuste
aprslenomdelobjetlorsdesoninstanciation:
chaines1;
chaines2(200);

//Instancieunechanedecaractres
//noninitialise.
//Instancieunechanedecaractres
//de200caractres.

Lesconstructeursdevrontparfoiseffectuerdestchespluscompliquesquecellesdonnesdanscet
exemple. Engnral, ilspeuvent fairetouteslesoprationsfaisablesdansunemthodenormale,
saufutiliserlesdonnesnoninitialisesbienentendu. Enparticulier, lesdonnesdessousobjets
dunobjetnesontpasinitialisestantquelesconstructeursdesclassesdebasenesontpasappels.
Cestpourcelaquilfauttoujoursappelerlesconstructeursdesclassesdebaseavantdexcuterle
constructeurdelaclasseencoursdinstanciation. Silesconstructeursdesclassesdebasenesont
pasappelsexplicitement, lecompilateurappellera, pardfaut, lesconstructeursdesclassesmres
quineprennentpasdeparamtreoudonttouslesparamtresontunevaleurpardfaut(et,siaucun
constructeurnestdfinidanslesclassemres,ilappelleralesconstructeurspardfautdecesclasses).
Commentappelerlesconstructeursetlesdestructeursdesclassesmreslorsdelinstanciationetdela
destructionduneclassedrive?Lecompilateurnepeuteneffetpassavoirquelconstructeurilfaut
appelerparmilesdiffrentsconstructeurssurchargspotentiellementprsents...Pourappelerunautre
constructeurduneclassedebasequeleconstructeurneprenantpasdeparamtre, ilfautspcifier
explicitementceconstructeuravecsesparamtresaprslenomduconstructeurdelaclassefille,en
lessparantdedeuxpoints(:).
Enrevanche,ilestinutiledeprciserledestructeurappeler,puisqueceluiciestunique.Leprogram
meurnedoitdoncpasappelerluimmelesdestructeursdesclassesmres,lelangagesencharge.
Exemple811.Appelduconstructeurdesclassesdebase
/*Dclarationdelaclassemre.*/
classMere
{
intm_i;
public:
Mere(int);
~Mere(void);
};
/*Dfinitionduconstructeurdelaclassemre.*/
Mere::Mere(inti)
{
m_i=i;
printf("Excutionduconstructeurdelaclassemre.\n");
return;
}

106

Chapitre8.C++:lacoucheobjet

/*Dfinitiondudestructeurdelaclassemre.*/
Mere::~Mere(void)
{
printf("Excutiondudestructeurdelaclassemre.\n");
return;
}
/*Dclarationdelaclassefille.*/
classFille:publicMere
{
public:
Fille(void);
~Fille(void);
};
/*Dfinitionduconstructeurdelaclassefille
avecappelduconstructeurdelaclassemre.*/
Fille::Fille(void):Mere(2)
{
printf("Excutionduconstructeurdelaclassefille.\n");
return;
}
/*Dfinitiondudestructeurdelaclassefille
avecappelautomatiquedudestructeurdelaclassemre.*/
Fille::~Fille(void)
{
printf("Excutiondudestructeurdelaclassefille.\n");
return;
}

Lorsdelinstanciationdunobjetdelaclassefille,leprogrammeafficheradanslordrelesmessages
suivants:
Excutionduconstructeurdelaclassemre.
Excutionduconstructeurdelaclassefille.

etlorsdeladestructiondelobjet:
Excutiondudestructeurdelaclassefille.
Excutiondudestructeurdelaclassemre.

Si lonnavait pasprcisqueleconstructeurappelerpourlaclasseMeretait
leconstructeur
prenantunentierenparamtre,lecompilateurauraitessaydappelerleconstructeurpardfautde
cetteclasse.Or,ceconstructeurntantplusgnrautomatiquementparlecompilateur(causede
ladfinitiondunconstructeurprenantunparamtre),ilyauraiteuuneerreurdecompilation.
Ilestpossibledappelerplusieursconstructeurssilaclassedrivedeplusieursclassesdebase.Pour
cela,ilsuffitdelisterlesconstructeursunun,ensparantleursappelspardesvirgules.Onnotera
cependant quelordredanslequel lesconstructeurssont appelsnest pasforcment lordredans
lequel ilssont listsdansladfinitionduconstructeurdelaclassefille.
Eneffet, leC++appelle

107

Chapitre8.C++:lacoucheobjet
toujourslesconstructeursdanslordredapparitiondeleursclassesdanslalistedesclassesdebase
delaclassedrive.
leplusdrivdansune
Note:Afindviterlutilisationdesdonnesnoninitialisesdelobjet
hirarchiependantlaconstructiondesessousobjetsparlintermdiairedesfonctionsvirtuelles,
lemcanismedesfonctionsvirtuellesest dsactivdanslesconstructeurs(voyezlaSection
8.13pourplusdedtailssurlesfonctionsvirtuelles).Ceproblmesurvientparcequependant
lexcutiondesconstructeursdesclassesdebase,lobjetdelaclasseencoursdinstanciation
napasencoretinitialis,etmalgrcela,unefonctionvirtuelleauraitpuutiliserunedonnede
cetobjet.
Unefonctionvirtuellepeut donctoujourstreappeledansunconstructeur, maislafonction
effectivementappeleestcelledelaclassedusousobjetencoursdeconstruction:pascellede
laclassedelobjetcomplet.Ainsi,siuneclasseAhriteduneclasseBetquellesonttoutesles
deuxunefonctionvirtuelle f,lappel de f dansleconstructeurdeButiliseralafonction f deB,
pascelledeA(mmesilobjetqueloninstancieestdeclasseA).

Lasyntaxeutilisepourappelerlesconstructeursdesclassesdebasepeut galement treutilise


pourinitialiserlesdonnesmembresdelaclasse. Enparticulier, cettesyntaxeestobligatoirepour
lesdonnesmembresconstantesetpourlesrfrences,carleC++nepermetpaslaffectationdune
valeurdesvariablesdecetype. Encoreunefois, lordredappel desconstructeursdesdonnes
membresainsiinitialisesnestpasforcmentlordredanslequelilssontlistsdansleconstructeur
delaclasse.Eneffet,leC++utilisecettefoislordrededclarationdechaquedonnemembre.
Exemple812.Initialisationdedonnesmembresconstantes
classtableau
{
constintm_iTailleMax;
constint*m_pDonnees;
public:
tableau(intiTailleMax);
~tableau();
};
tableau::tableau(intiTailleMax):
m_iTailleMax(iTailleMax)
//Initialiseladonnemembreconstante.
{
//Allocationduntableaudem_iTailleMaxentres:
m_pDonnees=newint[m_iTailleMax];
}
tableau::~tableau()
{
//Destructiondesdonnes:
delete[]m_pDonnees;
}
Note:Lesconstructeursdesclassesdebasevirtuellesprenant desparamtresdoivent tre
appelsparchaqueclassequiendrive,quecettedrivationsoitdirecteouindirecte.Eneffet,les
classesdebasevirtuellessubissentuntraitementparticulierquiassurelunicitdeleursdonnes
danstoutesleursclassesdrives. Lesclassesdrivesnepeuvent doncpassereposersur
leursclassesdebasepour appeler leconstructeur desclassesvirtuelles, car il peut yavoir
plusieursclassesdebasesqui driventdunemmeclassevirtuelle, et celasupposerait que

108

Chapitre8.C++:lacoucheobjet
leconstructeurdecettedernireclasseserait appelplusieursfois, ventuellement avecdes
valeursdeparamtresdiffrentes. Chaqueclassedoit doncprendreenchargelaconstruction
dessousobjetsdesclassesdebasevirtuellesdontilhritedanscecas.

8.8.2.Constructeursdecopie
Ilfaudraparfoiscrerunconstructeurdecopie.
Lebutdecetypedeconstructeurestdinitialiser
unobjetlorsdesoninstanciationpartirdunautreobjet.
Touteclassedisposedunconstructeur
decopiepardfautgnrautomatiquementparlecompilateur,dontleseulbutestderecopierles
champsdelobjetrecopierunundansleschampsdelobjetinstancier.Toutefois,ceconstructeur
pardfautnesuffirapastoujours,etleprogrammeurdevraparfoisenfournirunexplicitement.
Ceseranotammentlecaslorsquecertainesdonnesdesobjetsauronttallouesdynamiquement.
Unecopiebrutaledeschampsdunobjetdansunautreneferaitquerecopierlespointeurs,pasles
donnespointes.Ainsi,lamodificationdecesdonnespourunobjetentraneraitlamodificationdes
donnesdelautreobjet,cequineseraitsansdoutepasleffetdsir.
Ladfinitiondesconstructeursdecopiesefaitcommecelledesconstructeursnormaux.Lenomdoit
treceluidelaclasse,etilnedoityavoiraucuntype.Danslalistedesparamtrescependant,ildevra
toujoursyavoirunerfrencesurlobjetcopier.
Pourlaclassechainedfiniecidessus,ilfautunconstructeurdecopie.Celuicipeuttredclarde
lafaonsuivante:
chaine(constchaine&Source);

o Source estlobjetcopier.
Si lonrajouteladonnemembre
constructeurpeuttre:

Taille

dansladclarationdelaclasse,

ladfinitiondece

chaine::chaine(constchaine&Source)
{
inti=0;
//Compteurdecaractres.
Taille=Source.Taille;
s=newchar[Taille+1];
//Effectuelallocation.
strcpy(s,Source.s);
//Recopielachanedecaractressource.
return;
}

Leconstructeurdecopieest appeldanstouteinstanciationavecinitialisation, commecellesqui


suivent:
chaines2(s1);
chaines2=s1;

Danslesdeuxexemples,cestleconstructeurdecopiequiestappel.Enparticulier,ladeuxime
ligne,leconstructeurnormalnestpasappeletaucuneaffectationentreobjetsnalieu.

109

Chapitre8.C++:lacoucheobjet
Note:Lefaitdedfinirunconstructeurdecopiepouruneclassesignifiegnralementquele
constructeurdecopie,ledestructeuretloprateurdaffectationfournispardfautparlecompi
lateurneconviennent paspourcetteclasse. Parconsquent, cesmthodesdevront systma
tiquementtreredfiniestouteslestroisdsquelunedentreellelesera.Cettergle,quelon
appellela rgle des trois,vouspermettradviterdesboguesfacilement.Voustrouverezdeplus
amplesdtailssurlamanirederedfinirloprateurdaffectationdanslaSection8.11.3.

8.8.3.Utilisationdesconstructeursdanslestranstypages
Lesconstructeurssont utilissdanslesconversionsdetypedanslesquellesletypecibleest
celui
delaclasseduconstructeur.Cesconversionspeuventtresoitimplicites(dansuneexpression),soit
explicite(laideduntranstypage).Pardfaut,lesconversionsimplicitessontlgales,pourvuquil
existeunconstructeurdontlepremierparamtrealemmetypequelobjetsource.Parexemple,la
classeEntiersuivante:
classEntier
{
inti;
public:
Entier(intj)
{
i=j;
return;
}
};

disposedunconstructeurdetranstypagepourlesentiers.Lesexpressionssuivantes:
intj=2;
Entiere1,e2=j;
e1=j;

sontdonclgales,lavaleurentiresitueladroitedelexpressiontantconvertieimplicitementen
unobjetdutypedelaclasseEntier.
Si,pouruneraisonquelconque,cecomportementnestpassouhaitable,onpeutforcerlecompilateur
naccepterquelesconversionsexplicites(laidedetranstypage).Pourcela,ilsuffitdeplacerlemot
cl explicit avantladclarationduconstructeur.Parexemple,leconstructeurdelaclassechaine
vuecidessusprenantunentierenparamtrerisquedtreutilisdansdesconversionsimplicites.
Orceconstructeurnepermetpasdeconstruireunechanedecaractrespartirdunentier,
etne
doitdoncpastreutilisdanslesoprationsdetranstypage.Ceconstructeurdoitdonctredclar
explicit :
classchaine
{
size_tTaille;
char*s;
public:
chaine(void);
//Ceconstructeurpermetdeprciserlatailledelachane
//sacration:

110

Chapitre8.C++:lacoucheobjet
explicitchaine(unsignedint);
~chaine(void);
};

Aveccettedclaration,lexpressionsuivante:
intj=2;
chaines=j;

nestplusvalide,alorsquelleltaitlorsqueleconstructeurntaitpasdclar explicit.
Note:Onprendragardeaufaitquelemotcl explicit nempchelutilisationduconstructeur
danslesoprationsdetranstypagequedanslesconversionsimplicites.Siletranstypageestex
plicitementdemand,leconstructeurseramalgrtoututilis.Ainsi,lecodesuivantseraaccept:

intj=2;
chaines=(chaine)j;

Bienentendu,celanapasbeaucoupdesignificationetnedevraitjamaistreeffectu.

8.9.Pointeurthis
Nousallonsprsentvoircommentlesfonctionsmembres, quiappartiennentlaclasse, peuvent
accderauxdonnesdunobjet,quiestuneinstancedecetteclasse.Celaestindispensablepourbien
comprendrelesparagraphessuivants.
chaqueappeldunefonctionmembre,lecompilateurpasseimplicitementunpointeursurlesdon
nesdelobjetenparamtre.Ceparamtreestlepremierparamtredelafonction.Cemcanismeest
compltementinvisibleauprogrammeur,etnousnenousattarderonspasdessus.
Enrevanche,ilfautsavoirquelepointeursurlobjetestaccessiblelintrieurdelafonctionmembre.
Il portelenom this . Parconsquent, *this reprsentelobjet luimme. Nousverronsune
utilisationde this dansleparagraphesuivant(surchargedesoprateurs).
this estunpointeurconstant,cestdirequonnepeutpaslemodifier(ilestdoncimpossiblede

fairedesoprationsarithmtiquesdessus).Celaesttoutfaitnormal,puisquelefairereviendrait
sortirdelobjetencours(celuipourlequellamthodeencoursdexcutiontravaille).
Ilestpossibledetransformercepointeurconstantenunpointeurconstantsurdesdonnesconstantes
pourchaquefonctionmembre.Lepointeurnepeuttoujourspastremodifi,etlesdonnesdelobjet
nepeuventpastremodifiesnonplus.Lobjetestdoncconsidrparlafonctionmembreconcerne
commeunobjetconstant.Celarevientdirequelafonctionmembresinterditlamodificationdes
const lasuitedelenttedela
donnesdelobjet.Onparvientcersultatenajoutantlemotcl
fonctionmembre.Parexemple:
classEntier
{
inti;
public:

111

Chapitre8.C++:lacoucheobjet
intlit(void)const;
};
intEntier::lit(void)const
{
returni;
}

Danslafonctionmembre lit,ilestimpossibledemodifierlobjet.Onnepeutdoncaccderquen
lectureseule i.NousverronsuneapplicationdecettepossibilitdanslaSection8.15.
Ilestnoterquunemthodequinestpasdclarecommetant const modifieapriorilesdonnes
delobjetsurlequelelletravaille. Donc, sielleestappelesurunobjetdclar const, uneerreur
decompilationseproduit.Cecomportementestnormal.Ondevradonctoujoursdclarer const une
mthodequinemodifiepasrellementlobjet,afindelaisserlutilisateurlechoixdedclarer const
ounonlesobjetsdesaclasse.
Note:Lemot cl const nintervient pasdanslasignaturedesfonctionsengnral lorsquil
sappliqueauxparamtres(toutparamtredclarconst perdsaqualificationdanslasignature).
Enrevanche, il intervientdanslasignaturedunefonctionmembrequandil sappliquecette
fonction(ou,plusprcisment,lobjetpointpar this).Il estdoncpossiblededclarerdeux
fonctionsmembresacceptantlesmmesparamtres,dontuneseuleestconst.Lorsdelappel,
ladterminationdelafonctionutiliser dpendradelanaturedelobjet
sur lequel elledoit
sappliquer.Silobjetest const,lamthodeappeleseracellequiest const.

8.10.Donnesetfonctionsmembresstatiques
Nousallonsvoirdansceparagraphelemploidumotcl static danslesclasses.Cemotclinter
vientpourcaractriserlesdonnesmembresstatiquesdesclasses, lesfonctionsmembresstatiques
desclasses,etlesdonnesstatiquesdesfonctionsmembres.

8.10.1.Donnesmembresstatiques
Uneclassepeutcontenirdesdonnesmembresstatiques.Cesdonnessontsoitdesdonnesmembres
propreslaclasse,soitdesdonneslocalesstatiquesdesfonctionsmembresdelaclasse.Danstous
lescas,ellesappartiennentlaclasse,etnonpasauxobjetsdecetteclasse.Ellessontdonccommunes
touscesobjets.
Ilestimpossibledinitialiserlesdonnesduneclassedansleconstructeurdelaclasse,carleconstruc
teurninitialisequelesdonnesdesnouveauxobjets.Lesdonnesstatiquesnesontpasspcifiques
unobjetparticulieretnepeuventdoncpastreinitialisesdansleconstructeur.Enfait,leurinitia
lisationdoitsefairelorsdeleurdfinition,endehorsdeladclarationdelaclasse.Pourprciserla
classelaquellelesdonnesainsidfiniesappartiennent,ondevrautiliserloprateurdersolution
deporte( ::).
Exemple813.Donnemembrestatique
classtest
{

112

Chapitre8.C++:lacoucheobjet
staticinti;
...

//Dclarationdanslaclasse.

};
inttest::i=3;

//Initialisationendehorsdelaclasse.

Lavariable test::i serapartagepartouslesobjetsdeclassetest,etsavaleurinitialeest

3.

Note:Ladfinitiondesdonnesmembresstatiquessuitlesmmesrglesqueladfinitiondes
variablesglobales.Autrementdit,ellessecomportentcommedesvariablesdclaresexternes.
Ellessontdoncaccessiblesdanstouslesfichiersduprogramme(pourvu,bienentendu,quelles
soientdclaresenzonepubliquedanslaclasse).Demme,ellesnedoiventtredfiniesquune
seulefoisdanstoutleprogramme.Ilnefautdoncpaslesdfinirdansunfichierdenttequipeut
treinclusplusieursfoisdansdesfichierssources,
mmesi lonprotgecefichierdentte
contrelesinclusionsmultiples.

Lesvariablesstatiquesdesfonctionsmembresdoivent treinitialiseslintrieurdesfonctions
membres.Ellesappartiennentgalementlaclasse,etnonpasauxobjets.Deplus,leurporteest
rduitecelledublocdanslequelellesonttdclares.Ainsi,lecodesuivant:
#include <stdio.h>
classtest
{
public:
intn(void);
};
inttest::n(void)
{
staticintcompte=0;
returncompte++;
}
intmain(void)
{
testobjet1,objet2;
printf("%d",objet1.n()); //Affiche0
printf("%d\n",objet2.n()); //Affiche1
return0;
}

affichera 0 et 1,parcequelavariablestatique compte estlammepourlesdeuxobjets.

8.10.2.Fonctionsmembresstatiques
Lesclassespeuventgalementcontenirdesfonctionsmembresstatiques.Celapeutsurprendrepre
mirevue,puisquelesfonctionsmembresappartiennentdjlaclasse,cestdiretouslesobjets.
Enfait,celasignifiequecesfonctionsmembresnerecevrontpaslepointeursurlobjetthis,comme
cest lecaspourlesautresfonctionsmembres. Parconsquent, ellesnepourront accderquaux
donnesstatiquesdelobjet.

113

Chapitre8.C++:lacoucheobjet
Exemple814.Fonctionmembrestatique
classEntier
{
inti;
staticintj;
public:
staticintget_value(void);
};
intEntier::j=0;
intEntier::get_value(void)
{
j=1;
//Lgal.
returni;
//ERREUR!get_valuenepeutpasaccderi.
}

Lafonction get_value delexemplecidessusnepeutpasaccderladonnemembrenonstatique


i ,parcequellenetravaillesuraucunobjet.SonchampdactionestuniquementlaclasseEntier.En
revanche,ellepeutmodifierlavariablestatiquej ,puisquecelleciappartientlaclasseEntieretnon
auxobjetsdecetteclasse.
Lappeldesfonctionsmembrestatiquessefaitexactementcommeceluidesfonctionsmembresnon
statiques,enspcifiantlidentificateurdundesobjetsdelaclasseetlenomdelafonctionmembre,
sparsparunpoint.Cependant,commelesfonctionsmembresnetravaillentpassurlesobjetsdes
classesmaispluttsurlesclassesellesmmes,laprsencedelobjetlorsdelappelestfacultatif.On
peutdoncsecontenterdappelerunefonctionstatiqueenqualifiantsonnomdunomdelaclasse
laquelleelleappartientlaidedeloprateurdersolutiondeporte.
Exemple815.Appeldefonctionmembrestatique
classEntier
{
staticinti;
public:
staticintget_value(void);
};
intEntier::i=3;
intEntier::get_value(void)
{
returni;
}
intmain(void)
{
//Appellelafonctionstatiqueget_value:
intresultat=Entier::get_value();
return0;
}

Lesfonctionsmembresstatiquessontsouventutilisesafinderegrouperuncertainnombredefonc
tionnalitsenrapportavecleurclasse.Ainsi,ellessontfacilementlocalisableetlesrisquesdeconflits

114

Chapitre8.C++:lacoucheobjet
denomsentredeuxfonctionsmembreshomonymessontrduits.
Nousverronsgalementdansle
Chapitre11commentviterlesconflitsdenomsglobauxdanslecadredesespacesdenommage.

8.11.Surchargedesoprateurs
Onavuprcdemmentquelesoprateursnesediffrencientdesfonctionsquesyntaxiquement,pas
logiquement.Dailleurs,lecompilateurtraiteunappelunoprateurcommeunappelunefonction.
LeC++permetdoncdesurchargerlesoprateurspourlesclassesdfiniesparlutilisateur,enutilisant
unesyntaxeparticulirecalquesurlasyntaxeutilisepourdfinirdesfonctionsmembresnormales.
Enfait,ilestmmepossibledesurchargerlesoprateursdulangagepourlesclassesdelutilisateur
endehorsdeladfinitiondecesclasses. LeC++disposedoncdedeuxmthodesdiffrentespour
surchargerlesoprateurs.
Lesseulsoprateursquinepeuventpastresurchargssontlessuivants:
::
.
.*
?:
sizeof
typeid
static_cast
dynamic_cast
const_cast
reinterpret_cast

Touslesautresoprateurssontsurchargeables.Leursurchargeneposegnralementpasdeproblme
etpeuttreralisesoitdanslaclassedesobjetssurlesquelsilssappliquent,
soitlextrieurde
cetteclasse.Cependant,uncertainnombredentreeuxdemandentdesexplicationscomplmentaires,
quelondonneralafindecettesection.
Note:Onprendragardeauxproblmesdeperformanceslorsdelasurchargedesoprateurs.
Si lafacilitdcrituredesexpressionsutilisantdesclassesestgrandementsimplifiegrcela
possibilitdesurchargerlesoprateurspourcesclasses,lesperformancesduprogrammepeu
vententregravementaffectes.Eneffet,lutilisationinconsidredesoprateurspeutconduire
ungrandnombredecopiesdesobjets,copiesquelonpourraitviterencrivantleprogramme
classiquement.Parexemple,laplupartdesoprateursrenvoientunobjetdutypedelaclassesur
laquelleilstravaillent.Cesobjetssontsouventcrslocalementdanslafonctiondeloprateur
(cestdirequilssont deporte auto). Parconsquent, cesobjetssont temporaireset sont
dtruitslasortiedelafonctiondeloprateur.Celaimposedoncaucompilateurdenfaireune
copiedanslavaleurderetourdelafonctionavantdensortir.Cettecopieseraellemmedtruite
parlecompilateurunefoisquelleauratutiliseparlinstructionqui aappellafonction. Si
lersultatdoittreaffectunobjetdelappelant,unedeuximecopieinutileestralisepar
rapport aucasoloprateuraurait travailldirectement danslavariablersultat. Si lesbons
compilateurssontcapablesdvitercescopies,celarestelexceptionetilvautmieuxtreaverti
lavancepluttquededevoirrcriretoutsonprogrammeaposterioripourdesproblmesde
performances.

Nousallonsprsent voirdanslessectionssuivanteslesdeuxsyntaxespermettant desurcharger


lesoprateurspourlestypesdelutilisateur, ainsi quelesrglesspcifiquescertainsoprateurs
particuliers.

115

Chapitre8.C++:lacoucheobjet

8.11.1.Surchargedesoprateursinternes
Unepremiremthodepoursurchargerlesoprateursconsistelesconsidrercommedesmthodes
normalesdelaclassesurlaquelleilssappliquent. Lenomdecesmthodesestdonnparlemot
cl operator,suivideloprateursurcharger.Letypedelafonctiondeloprateurestletypedu
rsultatdonnparlopration, etlesparamtres, donnsentreparenthses, sontlesoprandes. Les
oprateursdecetypesontappelsoprateursinternes,parcequilssontdclarslintrieurdela
classe.
Voicilasyntaxe:
typeoperatorOp(paramtres)

lcriture
AOpB

setraduisantpar:
A.operatorOp(B)

Aveccettesyntaxe,lepremieroprandeesttoujourslobjetauquelcettefonctionsapplique.Cette
maniredesurchargerlesoprateursestdoncparticulirementbienadaptepourlesoprateursqui
modifient lobjet surlequel ilstravaillent, commeparexemplelesoprateurs =, +=, ++, etc. Les
paramtresdelafonctionoprateursontalorsledeuximeoprandeetlessuivants.
Lesoprateursdfiniseninternedevrontsouventrenvoyerlobjetsurlequelilstravaillent(cenest
pasunencessitcependant).Celaestfaisablegrceaupointeur this.
Parexemple,laclassesuivanteimplmentelesnombrescomplexesavecquelquesunesdeleursop
rationsdebase.
Exemple816.Surchargedesoprateursinternes
classcomplexe
{
doublem_x,m_y;
//Lespartiesrellesetimaginaires.
public:
//Constructeursetoprateurdecopie:
complexe(doublex=0,doubley=0);
complexe(constcomplexe&);
complexe&operator=(constcomplexe&);
//Fonctionspermettantdelirelespartiesrelles
//etimaginaires:
doublere(void)const;
doubleim(void)const;
//Lesoprateursdebase:
complexe&operator+=(constcomplexe&);
complexe&operator=(constcomplexe&);
complexe&operator*=(constcomplexe&);
complexe&operator/=(constcomplexe&);
};
complexe::complexe(doublex,doubley)

116

Chapitre8.C++:lacoucheobjet
{
m_x=x;
m_y=y;
return;
}
complexe::complexe(constcomplexe&source)
{
m_x=source.m_x;
m_y=source.m_y;
return;
}
complexe&complexe::operator=(constcomplexe&source)
{
m_x=source.m_x;
m_y=source.m_y;
return*this;
}
doublecomplexe::re()const
{
returnm_x;
}
doublecomplexe::im()const
{
returnm_y;
}
complexe&complexe::operator+=(constcomplexe&c)
{
m_x+=c.m_x;
m_y+=c.m_y;
return*this;
}
complexe&complexe::operator=(constcomplexe&c)
{
m_x=c.m_x;
m_y=c.m_y;
return*this;
}
complexe&complexe::operator*=(constcomplexe&c)
{
doubletemp=m_x*c.m_xm_y*c.m_y;
m_y=m_x*c.m_y+m_y*c.m_x;
m_x=temp;
return*this;
}
complexe&complexe::operator/=(constcomplexe&c)
{
doublenorm=c.m_x*c.m_x+c.m_y*c.m_y;
doubletemp=(m_x*c.m_x+m_y*c.m_y)/norm;
m_y=(m_x*c.m_y+m_y*c.m_x)/norm;

117

Chapitre8.C++:lacoucheobjet
m_x=temp;
return*this;
}
Note: LabibliothquestandardC++fournit uneclassetraitant lesnombrescomplexesde
manirecomplte,laclassecomplex.Cetteclassenestdoncdonneiciqutitredexempleet
nedevravidemment pastreutilise. Ladfinitiondesnombrescomplexeset
deleur
principalespropritsseradonnedanslaSection14.3.1,olaclassecomplexseradcrite.

Lesoprateursdaffectationfournissentunexempledutilisationdupointeur this. Cesoprateurs


renvoienteneffetsystmatiquementlobjetsurlequelilstravaillent,afindepermettredesaffectations
multiples.Lesoprateursdecetypedevrontdonctousseterminerpar:
return*this;

8.11.2.Surchargedesoprateursexternes
Unedeuximepossibilitnousestofferteparlelangagepoursurchargerlesoprateurs.Ladfinition
deloprateurnesefaitplusdanslaclassequilutilise,maisendehorsdecelleci,parsurchargedun
oprateurdelespacedenommageglobal.Ilsagitdoncdoprateursexternescettefois.
Lasurchargedesoprateursexternessefaitdoncexactementcommeonsurchargelesfonctionsnor
males.Danscecas,touslesoprandesdeloprateurdevronttrepasssenparamtres:ilnyaura
pasdeparamtreimplicite(lepointeur this nestpaspassenparamtre).
Lasyntaxeestlasuivante:
typeoperatorOp(oprandes)

o oprandes estlalistecompltedesoprandes.
Lavantagedecettesyntaxeest queloprateurest rellement symtrique, contrairement cequi
sepassepourlesoprateursdfinislintrieurdelaclasse. Ainsi, silutilisationdecetoprateur
ncessiteuntranstypagesurlundesoprandes,ilnestpasncessairequecetoprandesoitobliga
toirementledeuxime.Doncsilaclassedisposedeconstructeurspermettantdeconvertiruntypede
donneensonpropetype,cetypededonnepeuttreutilisavectouslesoprateursdelaclasse.
Parexemple,lesoprateursdaddition,desoustraction,demultiplicationetdedivisiondelaclasse
complexepeuventtreimplmentscommedanslexemplesuivant.
Exemple817.Surchargedoprateursexternes
classcomplexe
{
friendcomplexeoperator+(constcomplexe&,constcomplexe&);
friendcomplexeoperator(constcomplexe&,constcomplexe&);
friendcomplexeoperator*(constcomplexe&,constcomplexe&);
friendcomplexeoperator/(constcomplexe&,constcomplexe&);
doublem_x,m_y; //Lespartiesrellesetimaginaires.
public:
//Constructeursetoprateurdecopie:

118

Chapitre8.C++:lacoucheobjet
complexe(doublex=0,doubley=0);
complexe(constcomplexe&);
complexe&operator=(constcomplexe&);
//Fonctionspermettantdelirelespartiesrelles
//etimaginaires:
doublere(void)const;
doubleim(void)const;
//Lesoprateursdebase:
complexe&operator+=(constcomplexe&);
complexe&operator=(constcomplexe&);
complexe&operator*=(constcomplexe&);
complexe&operator/=(constcomplexe&);
};
//Lesoprateursdebaseonttludsici:
...
complexeoperator+(constcomplexe&c1,constcomplexe&c2)
{
complexeresult=c1;
returnresult+=c2;
}
complexeoperator(constcomplexe&c1,constcomplexe&c2)
{
complexeresult=c1;
returnresult=c2;
}
complexeoperator*(constcomplexe&c1,constcomplexe&c2)
{
complexeresult=c1;
returnresult*=c2;
}
complexeoperator/(constcomplexe&c1,constcomplexe&c2)
{
complexeresult=c1;
returnresult/=c2;
}

Aveccesdfinitions,ilestparfaitementpossibledeffectuerlamultiplicationdunobjetdetypecom
plexeavecunevaleurdetypedouble.Eneffet,cettevaleurseraautomatiquementconvertieencom
plexegrceauconstructeurdelaclassecomplexe,quiserautilisicicommeconstructeurdetransty
page.Unefoiscetteconversioneffectue,loprateuradquatestappliqu.
Onconstateraquelesoprateursexternesdoiventtredclarscommetantdesfonctionsamiesdela
classesurlaquelleilstravaillent,fautedequoiilsnepourraientpasmanipulerlesdonnesmembres
deleursoprandes.
Note:Certainscompilateurspeuvent supprimerlacrationdesvariablestemporaireslorsque
cellescisontutilisesentantquevaleurderetourdesfonctions.Celapermetdamliorergrande
mentlefficacitdesprogrammes,ensupprimanttouteslescopiesdobjetsinutiles.Cependant
cescompilateurssontrelativementraresetpeuventexigerunesyntaxeparticulirepoureffectuer

119

Chapitre8.C++:lacoucheobjet
cetteoptimisation.Gnralement,lescompilateursC++actuelssupprimentlacrationdevari
abletemporairedanslesretoursdefonctionssilavaleurderetourestconstruitedanslinstruction
return ellemme.Parexemple,loprateurdadditionpeuttreoptimisainsi:
complexeoperator+(constcomplexe&c1,constcomplexe&c2)
{
returncomplexe(c1.m_x+c2.m_x,c1.m_y+c2.m_y);
}

Cettecriturenestcependantpastoujoursutilisable,etloptimisationnestpasgarantie.

Lasyntaxedesoprateursexternespermetgalementdimplmenterlesoprateurspourlesquelsle
typedelavaleurderetourestceluideloprandedegaucheetqueletypedecetoprandenestpas
uneclassedfinieparlutilisateur(parexemplesicestuntypeprdfini).Eneffet,onnepeutpas
dfinirloprateurlintrieurdelaclassedupremieroprandedanscecas,puisquecetteclasseest
djdfinie.Demme,cettesyntaxepeuttreutiledanslecasdelcrituredoprateursoptimiss
pourcertainstypesdedonnes,pourlesquelslesoprationsralisesparloprateursontplussimples
quecellesquiauraientteffectuesaprstranstypage.
Parexemple,silonveutoptimiserlamultiplicationgaucheparunscalairepourlaclassecomplexe,
ondevraprocdercommesuit:
complexeoperator*(doublek,constcomplexe&c)
{
complexeresult(c.re()*k,c.im()*k);
returnresult;
}

cequipermettradcriredesexpressionsdutype:
complexec1,c2;
doubler;
...
c1=r*c2;

Lapremiresyntaxenauraitpermisdcrireunteloprateurquepourlamultiplicationdroitepar
undouble.Eneffet,pourcrireunoprateurinternepermettantderalisercetteoptimisation,ilaurait
fallusurchargerloprateurdemultiplicationdelaclassedoublepourluifaireaccepterunobjetde
typecomplexeensecondoprande...

8.11.3.Oprateursdaffectation
Nousavonsdjvuunexempledoprateurdaffectationaveclaclassecomplexecidessus.
Cet
oprateurtaittrssimple, maiscenestgnralementpastoujourslecas, etlimplmentationdes
oprateursdaffectationpeutparfoissouleverquelquesproblmes.
Premirement, commenous lavons dit dans laSection8.8.2, lefait dedfinir unoprateur
daffectationsignalesouventquelaclassenapasunestructuresimpleetque,
parconsquent, le
constructeurdecopieetledestructeurfournispardfautparlecompilateurnesuffisentpas.Ilfaut
doncveillerrespecterlargledestrois,quistipulequesilunedecesmthodesestredfinie,ilfaut
quelestroislesoient.Parexemple,sivousneredfinissezpasleconstructeurdecopie,lescritures
tellesque:

120

Chapitre8.C++:lacoucheobjet
classeobject=source;

nefonctionneront pascorrectement. Eneffet, cest leconstructeurdecopiequi est appelici, et


nonloprateurdaffectationcommeonpourraitlepenserpremirevue.Demme,lestraitements
particulierseffectuslorsdelacopieoudelinitialisationdunobjetdevronttreeffectusenordre
inversedansledestructeurdelobjet.Lestraitementsdedestructionconsistentgnralementlibrer
lammoireettouteslesressourcesallouesdynamiquement.
Lorsqueloncritunoprateurdaffectation,onagnralementreproduire,peudechosesprs,le
mmecodequeceluiquisetrouvedansleconstructeurdecopie.Ilarrivemmeparfoisquelondoive
librerlesressourcesexistantesavantdefairelaffectation,etdonclecodedeloprateurdaffectation
ressemblesouventlaconcatnationducodedudestructeuretducodeduconstructeurdecopie.Bien
entendu,cetteduplicationdecodeestgnanteetpeulgante.Unesolutionsimpleestdimplmenter
unefonctiondeduplicationetunefonctiondelibrationdesdonnes.Cesdeuxfonctions,parexemple
reset et clone, pourronttreutilisesdansledestructeur, leconstructeurdecopieetloprateur
daffectation. Leprogrammedevientainsiplusbeaucoupplussimple. Ilnefautgnralementpas
utiliserloprateurdaffectationdansleconstructeurdecopie, carcelapeut poserdesproblmes
complexesrsoudre.Parexemple,ilfautsassurerqueloprateurdecopienecherchepasutiliser
desdonnesmembresnoninitialiseslorsdesonappel.
Unautreproblmeimportantestceluidelautoaffectation. Nonseulementaffecterunobjetlui
mmeestinutileetconsommateurderessources, maisenpluscelapeuttredangereux. Eneffet,
laffectationrisquededtruirelesdonnesmembresdelobjetavantmmequellesnesoientcopies,
cequi provoquerait enfindecomptesimplement ladestructiondelobjet !Unesolutionsimple
consisteiciajouteruntestsurlobjetsourceendbutdoprateur,commedanslexemplesuivant:
classe&classe::operator=(constclasse&source)
{
if(&source!=this)
{
//Traitementdecopiedesdonnes:
...
}
return*this;
}

Enfin,lacopiedesdonnespeutlanceruneexceptionetlaisserlobjetsurlequellaffectationsefait
dansuntatindtermin.Lasolutionlaplussimpledanscecasestencoredeconstruireunecopie
delobjetsourceenlocal,puisdchangerlecontenudesdonnesdelobjetaveccettecopie.Ainsi,
silacopiechouepouruneraisonouuneautre,lobjetsourcenestpasmodifietrestedansuntat
stable.Lepseudocodepermettantderaliserceciestlesuivant:
classe&classe::operator=(constclasse&source)
{
//Construitunecopietemporairedelasource:
classTemp(source);
//changelecontenudecettecopieaveclobjetcourant:
swap(Temp,*this);
//Renvoielobjetcourant(modifi)etdtruitlesdonnes
//delavariabletemporaire(contenantlesanciennesdonnes):
return*this;
}

121

Chapitre8.C++:lacoucheobjet
Note:Leproblmedeltat desobjetsnest passpcifiqueloprateurdaffectation, mais
touteslesmthodesqui modifientlobjet,donc,enpratique,touteslesmthodesnon const.
Lcrituredeclassessresauniveaudelagestiondeserreursestdoncrelativementdifficile.
VoustrouverezdeplusamplesinformationssurlemcanismedesexceptionsenC++dansle
Chapitre9.

8.11.4.Oprateursdetranstypage
NousavonsvudanslaSection8.8.3quelesconstructeurspeuventtreutilisspourconvertirdes
objetsdutypedeleurparamtreversletypedeleurclasse. Cesconversionspeuventavoirlieude
manireimpliciteounon,selonquelemotcl explicit estappliquauconstructeurenquestion.
Cependant, il nest pastoujoursfaisabledcrireuntel constructeur. Parexemple, laclassecible
peutparfaitementtreunedesclassesdelabibliothquestandard,dontonnedoitvidemmentpas
modifierlesfichierssource, oummeundestypesdebasedulangage,pourlequelilnyapasde
dfinition.Heureusement,lesconversionspeuventmalgrtouttreralisesdanscecas,simplement
ensurchargeantlesoprateursdetranstypage.
Prenonslexempledelaclassechaine,quipermetdefairedeschanesdecaractresdynamiques(de
longueurvariable).IlestpossibledelesconvertirenchaneCclassiques(cestdireentableaude
caractres)siloprateur (charconst*) atsurcharg:
chaine::operatorcharconst*(void)const;

Onconstateraquecetoprateurnattendaucunparamtre,puisquilsappliquelobjetquilappelle,
maissurtout il napasdetype. Eneffet, puisquecest unoprateurdetranstypage, sontypeest
ncessairementceluiquiluicorrespond(danslecasprsent,charconst*).
Note:Si unconstructeurdetranstypageestgalementdfinidanslaclassedutypecibledela
conversion,il peutexisterdeuxmoyensderaliserletranstypage.Danscecas,lecompilateur
choisiratoujoursleconstructeurdetranstypagedelaclasseciblelaplacedeloprateurde
transtypage,saufsilestdclar explicit .Cemotclpeutdonctreutilispartoutolonveut
viterquelecompilateurnutiliseleconstructeurdetranstypage.Cependant,cettetechniquene
fonctionnequaveclesconversionsimplicitesralisesparlecompilateur.Silutilisateureffectue
untranstypageexplicite,ceseranouveauleconstructeurquiseraappel.
Deplus,lesconversionsralisesparlintermdiairedunconstructeursontsouventplusperfor
mantesquecellesralisesparlintermdiairedunoprateurdetranstypage,enraisondufait
quelonviteainsilacopiedelavariabletemporairedansleretourdeloprateurdetranstypage.
Onviteradoncdedfinirlesoprateursdetranstypageautantquefairesepeut,etoncrirade
prfrencedesconstructeursdanslesclassesdestypesciblesdesconversionsralises.

8.11.5.Oprateursdecomparaison
Lesoprateursdecomparaisonsonttrssimplessurcharger.Laseulechoseessentielleretenirest
quilsrenvoientunevaleurboolenne. Ainsi, pourlaclassechaine, onpeutdclarerlesoprateurs

122

Chapitre8.C++:lacoucheobjet
dgalitetdinfriorit(danslordrelexicographiqueparexemple)dedeuxchanesdecaractres
commesuit:
boolchaine::operator==(constchaine&)const;
boolchaine::operator<(constchaine&)const;

8.11.6.Oprateursdincrmentationetdedcrmentation
Lesoprateursdincrmentationetdedcrmentationsonttouslesdeuxdoubles,cestdirequela
mmenotationreprsentedeuxoprateursenralit. Eneffet, ilsnontpaslammesignification,
selonquilssontplacsavantouaprsleuroprande.Leproblmeestquecommecesoprateursne
prennentpasdeparamtres(ilsnetravaillentquesurlobjet),ilestimpossibledelesdiffrencierpar
surcharge.Lasolutionquiatadopteestdelesdiffrencierendonnantunparamtrefictifdetype
intlundentreeux.Ainsi,lesoprateurs ++ et neprennentpasdeparamtrelorsquilsagitdes
oprateursprfixs,etontunargumentfictif(quelonnedoitpasutiliser)lorsquilssontsuffixs.Les
versionsprfixesdesoprateursdoiventrenvoyerunerfrencesurlobjetluimme, lesversions
suffixesenrevanchepeuventsecontenterderenvoyerlavaleurdelobjet.
Exemple818.Oprateursdincrmentationetdedcrmentation
classEntier
{
inti;
public:
Entier(intj)
{
i=j;
return;
}
Entieroperator++(int)
{
Entiertmp(i);
++i;
returntmp;
}

//Oprateursuffixe:
//retournelavaleuretincrmente
//lavariable.

Entier&operator++(void)//Oprateurprfixe:incrmente
{
//lavariableetlaretourne.
++i;
return*this;
}
};
Note:Lesoprateurssuffixscrant desobjetstemporaires, ilspeuvent nuiregravement aux
performancesdesprogrammesquilesutilisentdemanireinconsidre.Parconsquent,onne
lesutiliseraquelorsquecelaest rellement ncessaire. Enparticulier, onviteradutiliserces
oprateursdanstouteslesoprationsdincrmentationdesbouclesditration.

123

Chapitre8.C++:lacoucheobjet

8.11.7.Oprateurfonctionnel
Loprateurdappeldefonctions () peutgalementtresurcharg.Cetoprateurpermetderaliser
desobjetsquisecomportentcommedesfonctions(cequelonappelledesfoncteurs).Labibliothque
standardC++enfaitunusageintensif,commenouspourronsleconstaterdansladeuximepartiede
cedocument.
Loprateurfonctionnelestgalementtrsutileenraisondesonnarit(*, /,etc.sontdesoprateurs
binairescarilsontdeuxoprandes, ?: estunoprateurternairecarilatroisoprandes, () estnaire
carilpeutavoirnoprandes).Ilestdoncutiliscourammentpourlesclassesdegestiondematrices
denombres,afindautoriserlcriture matrice(i,j,k) .
Exemple819.Implmentationduneclassematrice
classmatrice
{
typedefdouble*ligne;
ligne*lignes;
unsignedshortintn;
unsignedshortintm;

//Nombredelignes(1erparamtre).
//Nombredecolonnes(2meparamtre).

public:
matrice(unsignedshortintnl,unsignedshortintnc);
matrice(constmatrice&source);
~matrice(void);
matrice&operator=(constmatrice&m1);
double&operator()(unsignedshortinti,unsignedshortintj);
doubleoperator()(unsignedshortinti,unsignedshortintj)const;
};
//Leconstructeur:
matrice::matrice(unsignedshortintnl,unsignedshortintnc)
{
n=nl;
m=nc;
lignes=newligne[n];
for(unsignedshortinti=0;i<n;++i)
lignes[i]=newdouble[m];
return;
}
//Leconstructeurdecopie:
matrice::matrice(constmatrice&source)
{
m=source.m;
n=source.n;
lignes=newligne[n];
//Alloue.
for(unsignedshortinti=0;i<n;++i)
{
lignes[i]=newdouble[m];
for(unsignedshortintj=0;j
<m;++j) //Copie.
lignes[i][j]=source.lignes[i][j];
}
return;
}
//Ledestructeur:

124

Chapitre8.C++:lacoucheobjet
matrice::~matrice(void)
{
for(unsignedshortinti=0;i <n;++i)
delete[]lignes[i];
delete[]lignes;
return;
}
//Loprateurdaffectation:
matrice&matrice::operator=(constmatrice&source)
{
if(&source!=this)
{
if(source.n!=n||source.m!=m)
//Vrifielesdimensions.
{
for(unsignedshortinti=0;i
<n;++i)
delete[]lignes[i];
delete[]lignes;
//Dtruit...
m=source.m;
n=source.n;
lignes=newligne[n];
//etralloue.
for(i=0;i <n;++i)lignes[i]=newdouble[m];
}
for(unsignedshortinti=0;i
<n;++i)//Copie.
for(unsignedshortintj=0;j
<m;++j)
lignes[i][j]=source.lignes[i][j];
}
return*this;
}
//Oprateursdaccs:
double&matrice::operator()(unsignedshortinti,
unsignedshortintj)
{
returnlignes[i][j];
}
doublematrice::operator()(unsignedshortinti,
unsignedshortintj)const
{
returnlignes[i][j];
}

Ainsi,onpourraeffectuerladclarationdunematriceavec:
matricem(2,3);

etaccderseslmentssimplementavec:
m(i,j)=6;

Onremarqueraquelonadfinideuxoprateursfonctionnelsdanslexempledonncidessus. Le
premierrenvoieunerfrenceetpermetdemodifierlavaleurdundeslmentsdelamatrice.Cet
oprateurnepeutbienentendupassappliquerunematriceconstante,mmesimplementpourlire

125

Chapitre8.C++:lacoucheobjet
unlment. Cest doncledeuximeoprateurqui serautilispourlireleslmentsdesmatrices
constantes,carilrenvoieunevaleuretnonplusunerfrence.Lechoixdeloprateurutiliserest
dterminparlaprsencedumotcl const,quiindiquequeseulcetoprateurpeuttreutilispour
unematriceconstante.
Note:Lesoprationsdebasesurlesmatrices(addition,soustraction,inversion,transposition,
etc.)nontpastreportesici parsouci declart.Lamanirededfinircesoprateursat
prsentedanslessectionsprcdentes.

8.11.8.Oprateursdindirectionetdedrfrencement
Loprateurdedrfrencement* permetlcrituredeclassesdontlesobjetspeuventtreutilissdans
desexpressionsmanipulantdespointeurs.Loprateurdindirection& quantlui,permetderenvoyer
uneadresseautrequecelledelobjetsurlequelilsapplique.Enfin,loprateurdedrfrencement
etdeslectiondemembresdestructures > permetderaliserdesclassesquiencapsulentdautres
classes.
Si lesoprateursdedrfrencement et dindirection & et * peuvent renvoyerunevaleurdetype
quelconque,cenestpaslecasdeloprateurdedrfrencementetdeslectiondemembre >.Cet
oprateurdoitncessairementrenvoyeruntypepourlequelildoitencoretreapplicable.Cetypedoit
doncsoitsurchargerloprateur >,soittreunpointeursurunestructure,unionouclasse.
Exemple820.Oprateurdedrfrencementetdindirection
//Cetteclasseestencapsuleparuneautreclasse:
structEncapsulee
{
inti;
//Donneaccder.
};
Encapsuleeo;

//Objetmanipuler.

//Cetteclasseestlaclasseencapsulante:
structEncapsulante
{
Encapsulee*operator>(void)const
{
return&o;
}
Encapsulee*operator&(void)const
{
return&o;
}
Encapsulee&operator*(void)const
{
returno;
}
};
//Exempledutilisation:
voidf(inti)

126

Chapitre8.C++:lacoucheobjet
{
Encapsulantee;
e>i=2;
//Enregistre2danso.i.
(*e).i=3;
//Enregistre3danso.i.
Encapsulee*p=&e;
p>i=4;
//Enregistre4danso.i.
return;
}

8.11.9.Oprateursdallocationdynamiquedemmoire
Lesoprateurslesplusdifficilescriresontsansdoutelesoprateursdallocationdynamiquede
mmoire.Cesoprateursprennentunnombrevariabledeparamtres,parcequilssontcompltement
surchargeables(cestdirequilestpossiblededfinirplusieurssurchargesdecesoprateursmme
auseindunemmeclasse, silssont dfinisdemanireinterne). Il est doncpossiblededfinir
plusieursoprateurs new ou new[], etplusieursoprateurs delete ou delete[]. Cependant, les
premiersparamtresdecesoprateursdoiventtoujourstrelatailledelazonedelammoireallouer
danslecasdesoprateurs new et new[],etlepointeursurlazonedelammoirerestituerdansle
casdesoprateurs delete et delete[].
Laformelaplussimplede new neprendquunparamtre:lenombredoctetsallouer, quivaut
toujourslatailledelobjetconstruire.Ildoitrenvoyerunpointeurdutypevoid.Loprateur delete
correspondant peut prendre, quant lui, soit un, soit deuxparamtres. Commeonladjdit, le
premierparamtreesttoujoursunpointeurdutypevoidsurlobjetdtruire.Ledeuximeparamtre,
silexiste,estdutypesize_tetcontientlatailledelobjetdtruire.Lesmmesrglessappliquent
pourlesoprateurs new[] et delete[],utilisspourlestableaux.
Lorsquelesoprateurs delete et delete[] prennentdeuxparamtres,ledeuximeparamtreest
latailledelazonedelammoirerestituer.Celasignifiequelecompilateursechargedemmoriser
cetteinformation.Pourlesoprateurs new et delete,celanecausepasdeproblme,puisquelataille
decettezoneestfixeparletypedelobjet.Enrevanche,pourlestableaux,latailledutableaudoit
trestockeavecletableau.Engnral,lecompilateurutiliseunenttedevantletableaudobjets.
Cestpourcelaquelatailleallouerpasse new[],quiestlammequelatailledsallouerpasse
enparamtre delete[],nestpasgalelatailledunobjetmultiplieparlenombredobjetsdu
tableau.Lecompilateurdemandeunpeuplusdemmoire,pourmmoriserlatailledutableau.On
nepeutdoncpas,danscecas,fairedhypothsesquantlastructurequelecompilateurdonnerala
mmoireallouepourstockerletableau.
Enrevanche,si delete[] neprendenparamtrequelepointeursurletableau,lammorisationdela
new[] lavaleur
tailledutableauestlachargeduprogrammeur.Danscecas,lecompilateurdonne
exactedelatailledutableau,savoirlatailledunobjetmultiplieparlenombredobjetsdansle
tableau.
Exemple821.Dterminationdelatailledelenttedestableaux
#include <stdio.h>
intbuffer[256];

//Bufferservantstockerletableau.

classTemp
{
chari[13];

//sizeof(Temp)doittrepremier.

public:

127

Chapitre8.C++:lacoucheobjet
staticvoid*operatornew[](size_ttaille)
{
returnbuffer;
}
staticvoidoperatordelete[](void*p,size_ttaille)
{
printf("Tailledelentte:%d\n",
taille(taille/sizeof(Temp))*sizeof(Temp));
return;
}
};
intmain(void)
{
delete[]newTemp[1];
return0;
}

Ilestnoterquaucundesoprateurs new, delete, new[] et delete[] nereoitlepointeur this


enparamtre:cesontdesoprateursstatiques.Celaestnormalpuisque,lorsquilssexcutent,soit
this nexistedoncpasencore(ou
lobjetnestpasencorecr,soitilestdjdtruit.Lepointeur
nestplusvalide)lorsdelappeldecesoprateurs.
Lesoprateurs new et new[] peuventavoiruneformeencoreunpeupluscomplique,quipermetde
leurpasserdesparamtreslorsdelallocationdelammoire.Lesparamtressupplmentairesdoivent
imprativementtrelesparamtresdeuxetsuivants,puisquelepremierparamtreindiquetoujoursla
tailledelazonedemmoireallouer.
Commelepremierparamtreestcalculparlecompilateur,ilnyapasdesyntaxepermettantdele
passerauxoprateurs new et new[].Enrevanche,unesyntaxespcialeestncessairepourpasserles
paramtressupplmentaires.Cettesyntaxeestdtaillecidessous.
Siloprateur new estdclardelamaniresuivantedanslaclasseclasse:
staticvoid*operatornew(size_ttaille,paramtres);
paramtres lalistedesparamtres
o taille est latailledelazonedemmoirealloueret
additionnels,alorsondoitlappeleraveclasyntaxesuivante:
new(paramtres)classe;

Lesparamtressontdoncpasssentreparenthsescommepourunefonctionnormale.Lenomdela
fonctionest new,etlenomdelaclassesuitlexpressionnew commedanslasyntaxesansparamtres.
Cetteutilisationde new estappelenewavecplacement.
Leplacementestsouventutilisafinderaliserdesrallocationsdemmoiredunobjetunautre.
Parexemple,silondoitdtruireunobjetalloudynamiquementetenreconstruireimmdiatement
unautredummetype,lesoprationssuivantessedroulent:
1.appeldudestructeurdelobjet(ralisparlexpression delete);
2.appeldeloprateur delete ;
3.appeldeloprateur new ;
4.appelduconstructeurdunouvelobjet(ralisparlexpression new).

128

Chapitre8.C++:lacoucheobjet

Celanestpastrsefficace,puisquelammoireestrestituepourtreallouedenouveauimmdiate
mentaprs.Ilestbeaucouppluslogiquederutiliserlammoiredelobjetdtruirepourlenouvel
objet,etdereconstruirecedernierdanscettemmoire.Celapeutsefairecommesuit:
1.appelexplicitedudestructeurdelobjetdtruire;
2.appelde new aveccommeparamtresupplmentairelepointeursurlobjetdtruit;
3.appelduconstructeurdudeuximeobjet(ralisparlexpression new).
Lappelde new nefaitalorsaucuneallocation:ongagneainsibeaucoupdetemps.
Exemple822.Oprateursnewavecplacement
#include <stdlib.h>
classA
{
public:
A(void)
{
return;
}
~A(void)
{
return;
}

//Constructeur.

//Destructeur.

//Loprateurnewsuivantutiliseleplacement.
//Ilreoitenparamtrelepointeursurlebloc
//utiliserpourlarequtedallocationdynamique
//demmoire.
staticvoid*operatornew(size_ttaille,A*bloc)
{
return(void*)bloc;
}
//Oprateurnewnormal:
staticvoid*operatornew(size_ttaille)
{
//Implmentation:
returnmalloc(taille);
}
//Oprateurdeletenormal:
staticvoidoperatordelete(void*pBlock)
{
free(pBlock);
return;
}
};
intmain(void)
{

129

Chapitre8.C++:lacoucheobjet
A*pA=newA;
pA>~A();
A*pB=new(pA)A;
deletepB;
return0;

//CrationdunobjetdeclasseA.
//LoprateurnewglobalduC++estutilis.
//AppelexplicitedudestructeurdeA.
//RutilisationdelammoiredeA.
//Destructiondelobjet.

Danscetexemple,lagestiondelammoireestraliseparlesoprateurs new et delete normaux.


Cependant,larutilisationdelammoireallouesefaitgrceunoprateur new avecplacement,
dfinipourloccasion.Cederniernefaitstrictementriendautrequederenvoyerlepointeurquon
luiapassenparamtre.Onnoteraquilestncessairedappelerexplicitementledestructeurdela
classeAavantderutiliserlammoiredelobjet,caraucuneexpressiondeletenesenchargeavant
larutilisationdelammoire.
Note:Lesoprateurs new et delete avecplacementprdfinisparlabibliothquestandardC++
effectuentexactementcequelesoprateursdecetexemplefont.Ilnestdoncpasncessairede
lesdfinir,si onnefaitaucunautretraitementquederutiliserleblocmmoirequeloprateur
new reoitenparamtre.

Ilestimpossibledepasserdesparamtresloprateur delete dansuneexpression delete.Cela


estdaufaitquengnralonneconnatpaslecontextedeladestructiondunobjet(alorsqu
lallocation, onconnat lecontextedecrationdelobjet). Normalement, il nepeut doncyavoir
quunseuloprateur delete.Cependant,ilexisteuncasolonconnatlecontextedelappelde
loprateur delete :cestlecasoleconstructeurdelaclasselanceuneexception(voirleCha
pitre9pourplusdedtailscesujet).
Danscecas, lammoirealloueparloprateur new doit
trerestitueet loprateur delete est automatiquement appel, puisquelobjet napasputre
construit. Afindobteniruncomportementsymtrique, ilestpermisdedonnerdesparamtresad
ditionnelsloprateur delete. Lorsquuneexceptionest lancedansleconstructeurdelobjet
allou, loprateur delete appelest loprateurdont lalistedesparamtrescorrespondcelle
deloprateur new quiatutilispourcrerlobjet. Lesparamtrespasssloprateur delete
prennent alorsexactement lesmmesvaleursquecellesqui
ont tdonnesauxparamtresde
loprateur new lorsdelallocationdelammoiredelobjet.
Ainsi, siloprateur new atutili
new a
ssansplacement,loprateur delete sansplacementseraappel.Enrevanche,siloprateur
delete
tappelavecdesparamtres,loprateur
quialesmmesparamtresseraappel.Siaucun
oprateur delete necorrespond,aucunoprateur delete nestappel(siloprateur new napas
alloudemmoire,celanestpasgrave,enrevanche,sidelammoireatalloue,elleneserapas
restitue).Ilestdoncimportantdedfinirunoprateurdelete avecplacementpourchaqueoprateur
new avecplacementdfini.Lexempleprcdentdoitdonctrercritdelamaniresuivante:
#include <stdlib.h>
staticboolbThrow=false;
classA
{
public:
A(void)
//Constructeur.
{
//Leconstructeurestsusceptible
//delanceruneexception:
if(bThrow)throw2;

130

Chapitre8.C++:lacoucheobjet
return;
}
~A(void)
{
return;
}

//Destructeur.

//Loprateurnewsuivantutiliseleplacement.
//Ilreoitenparamtrelepointeursurlebloc
//utiliserpourlarequtedallocationdynamique
//demmoire.
staticvoid*operatornew(size_ttaille,A*bloc)
{
return(void*)bloc;
}
//Loprateurdeletesuivantestutilisdanslesexpressions
//quiutilisentloprateurnewavecplacementcidessus,
//siuneexceptionseproduitdansleconstructeur.
staticvoidoperatordelete(void*p,A*bloc)
{
//Onnefaitrien,parcequeloprateurnewcorrespondant
//napasalloudemmoire.
return;
}
//Oprateurnewetdeletenormaux:
staticvoid*operatornew(size_ttaille)
{
returnmalloc(taille);
}
staticvoidoperatordelete(void*pBlock)
{
free(pBlock);
return;
}
};
intmain(void)
{
A*pA=newA;
pA>~A();
bThrow=true;

//CrationdunobjetdeclasseA.
//AppelexplicitedudestructeurdeA.
//Maintenant,leconstructeurdeAlance
//uneexception.

try
{
A*pB=new(pA)A;

//RutilisationdelammoiredeA.
//Siuneexceptionalieu,loprateur
//delete(void*,A*)avecplacement
//estutilis.
//Destructiondelobjet.

deletepB;
}
catch(...)
{
//Loprateurdelete(void*,A*)nelibrepaslammoire

131

Chapitre8.C++:lacoucheobjet
//allouelorsdupremiernew.Ilfautdoncquandmme
//lefaire,maissansdelete,carlobjetpointparpA
//estdjdtruit,etceluipointparpBlatpar
//loprateurdelete(void*,A*):
free(pA);
}
return0;
}

Note:Il estpossibledutiliserleplacementaveclesoprateursnew[] et delete[] exactement


delammemanirequaveclesoprateurs new et delete.
Onnoteraquelorsqueloprateur new est utilisavecplacement, si ledeuximeargument
est detypesize_t, loprateur delete deuxargumentspeut treinterprtsoit commeun
oprateur delete classiquesansplacementmaisavecdeuxparamtres,soitcommeloprateur
delete avecplacementcorrespondantloprateur new avecplacement.Afindersoudrecette
ambigut, lecompilateur interprtesystmatiquement loprateur delete avecundeuxime
paramtredetypesize_tcommetantloprateurdeuxparamtressansplacement.Ilestdonc
impossiblededfinirunoprateur delete avecplacementsil adeuxparamtres,ledeuxime
tantdetypesize_t.Ilenestdemmeaveclesoprateursnew[] et delete[] .

Quellequesoitlasyntaxequevousdsirezutiliser,lesoprateurs new, new[], delete et delete[]


doiventavoiruncomportementbiendtermin.Enparticulier,lesoprateurs delete et delete[]
doiventpouvoiraccepterunpointeurnulenparamtre. Lorsquuntelpointeurestutilisdansune
expression delete,aucuntraitementnedoittrefait.
Enfin,vosoprateurs new et new[] doivent,encasdemanquedemmoire,appelerungestionnaire
derreur.Legestionnairederreurfournipardfautlanceuneexceptiondeclassestd::bad_alloc(voir
leChapitre9pourplusdedtailssurlesexceptions).
Cetteclasseest dfiniecommesuit dansle
fichierdentte new :
classbad_alloc:publicexception
{
public:
bad_alloc(void)throw();
bad_alloc(constbad_alloc&)throw();
bad_alloc&operator=(constbad_alloc&)throw();
virtual~bad_alloc(void)throw();
virtualconstchar*what(void)constthrow();
};

std::.Si
Note:Commesonnomlindique,cetteclasseestdfiniedanslespacedenommage
vousnevoulezpasutiliserlesnotionsdesespacesdenommage,vousdevrezinclurelefichier
dentte new.h aulieude new.Vousobtiendrezdeplusamplesrenseignementssurlesespaces
denommagedansleChapitre11.

La classe exceptiondont bad_alloc hrite est dclare comme suit dans le fichier dentte
exception :
classexception
{

132

Chapitre8.C++:lacoucheobjet
public:
exception(void)throw();
exception(constexception&)throw();
exception&operator=(constexception&)throw();
virtual~exception(void)throw();
virtualconstchar*what(void)constthrow();
};

Note:VoustrouverezplusdinformationssurlesexceptionsdansleChapitre9.

Si vous dsirez remplacer le gestionnaire par dfaut, vous pouvez utiliser la fonction
std::set_new_handler. Cettefonctionattendenparamtrelepointeur
sur legestionnaire
derreur installer et renvoielepointeur sur legestionnairederreur prcdemment install.
Les gestionnaires derreurs neprennent aucunparamtreet nerenvoient aucunevaleur. Leur
comportementdoittrelesuivant:

soitilsprennentlesmesuresncessairespourpermettrelallocationdublocdemmoiredemand
etrendentlamainloprateur new.Cedernierrefaitalorsunetentativepourallouerleblocde
mmoire.Sicettetentativechouenouveau,legestionnairederreurestrappel.Cettebouclese
poursuitjusqucequeloprationsedroulecorrectementouquuneexceptionstd::bad_allocsoit
lance;

soitilslancentuneexceptiondeclassestd::bad_alloc;

soitilsterminentlexcutionduprogrammeencours.

new et new[],quiren
Labibliothquestandarddfinituneversionavecplacementdesoprateurs
voientlepointeurnulaulieudelanceruneexceptionencasdemanquedemmoire.Cesoprateurs
prennentundeuximeparamtre, detypestd::nothrow_t, quidoittrespcifilorsdelappel. La
bibliothquestandarddfinitunobjetconstantdecetypeafinquelesprogrammespuissentlutiliser
sansavoirledfinireuxmme.Cetobjetsenomme std::nothrow

Exemple823.Utilisationdenewsansexception
char*data=new(std::nothrow)char[25];
if(data==NULL)
{
//Traitementdelerreur...
.
.
.
}
Note:LaplupartdescompilateursnerespectentpaslesrglesdictesparlanormeC++.En
effet, ilsprfrent retournerlavaleurnulleencasdemanquedemmoireaulieudelancer
uneexception.Onpeutrendrecesimplmentationscompatiblesaveclanormeeninstallantun
gestionnairederreurquilanceluimmelexceptionstd::bad_alloc.

133

Chapitre8.C++:lacoucheobjet

8.12.Desentressortiessimplifies
Lesfluxdentre/sortiedelabibliothquestandardC++constituentsansdoutelunedesapplications
lesplusintressantesdelasurchargedesoprateurs. Commenousallonslevoir, lasurchargedes
oprateurs << et >> permetdcrireetdeliresurcesfluxdemaniretrsintuitive.
Eneffet,labibliothquestandardC++dfinitdanslentteiostream desclassesextrmementpuis
santespermettantdemanipulerlesfluxdentre/sortie.Cesclassesralisentenparticulierlesop
rationsdentre/sortiedeetverslespriphriquesdentreetlespriphriquesdesortiestandards
(gnralement, leclavieretlcran), maisellesnesarrtentpasl:ellespermettentgalementde
travaillersurdesfichiersouencoresurdestamponsenmmoire.
Lesclassesdentre/sortiedelabibliothquestandardC++permettentdoncdeffectuerlesmmes
oprationsquelesfonctions printf et scanf delabibliothqueCstandard. Cependant, grceau
mcanismedesurchargedesoprateurs, ellessontbeaucoupplusfacilesdutilisation. Eneffet, les
oprateurs << et >> decesclassesont tsurchargspourchaquetypededonnedulangage,
permettant ainsi deraliserdesentres/ sortiestypesextrmement facilement. Loprateur <<,
galementappeleoprateurdinsertion,serautilispourraliserdescrituressurunfluxdedonnes,
tandisqueloprateur >>,ouoprateurdextraction,permettraderaliserlalecturedunenouvelle
donnedanslefluxdentre.Cesdeuxoprateursrenvoienttouslesdeuxlefluxdedonnesutilis,
cequipermetderaliserplusieursoprationsdentre/sortiesuccessivementsurlemmeflux.
Note:Cettesectionnapaspourbutdedcrireendtail lesfluxdentre/sortiedelabiblio
thquestandardC++, maisplutt denfaireuneprsentationsimplepermettant delesutiliser
sansavoirseplongerprmaturmentdansdesnotionsextrmementvolues.Voustrouverez
unedescriptionexhaustivedesmcanismesdesfluxdentre/sortiedelabibliothquestandard
C++dansleChapitre15.

Labibliothquestandarddfinitquatreinstancesparticuliresdesesclassesdentre/sortie: cin,
cout, cerr et clog.Cesobjetssontdesinstancesdesclassesistreametostream,prenantrespecti
vementenchargelentreetlasortiedesdonnesdesprogrammes.Lobjet cin correspondauflux
dentrestandard stdin duprogramme, et lobjet cout auxfluxdesortiestandard stdout. En
fin,lesobjets cerr et clog sontassocisaufluxderreursstandard stderr.Thoriquement, cerr
doittreutilispourlcrituredesmessagesderreurdesprogrammes, et clog pourlesmessages
dinformation.Cependant,enpratique,lesdonnescritessurcesdeuxfluxsontcritesdanslemme
flux,etlemploidelobjet clog estassezrare.
Lutilisationdesoprateursdinsertionet
suivante:

dextractionsur cesfluxsersumedonclasyntaxe

cin >> variable[ >> variable[...]];


cout << valeur[ << valeur[...]];

Commeonlevoit,ilestpossibledeffectuerplusieursentresouplusieurssortiesuccessivementsur
unmmeflux.
Deplus,labibliothquestandarddfiniecequelonappelledesmanipulateurspermettantderaliser
desoprationssimplessurlesfluxdentre/sortie.Lemanipulateurleplusutilisestsansnuldoute
lemanipulateur endl qui,commesonnomlindique,permetdesignalerunefindeligneetdeffectuer
unsautdelignelorsquilestemploysurunfluxdesortie.
Exemple824.Fluxdentre/sortiecinetcout
#include <iostream>

134

Chapitre8.C++:lacoucheobjet

usingnamespacestd;
intmain(void)
{
inti;
//Litunentier:
cin >> i;
//Affichecetentieretlesuivant:
cout << i << "" << i+1 << endl;
return0;
}
Note:CommeonleverradansleChapitre15,lesmanipulateurssontenralitdesfonctions
pour letypedesquellesunoprateur << ouunoprateur >> atdfini danslesclasses
dentre/ sortie.Cesoprateursappellent cesfonctions, qui effectuent chacunedesmodifica
tionsspcifiquessurlefluxsurlequelellestravaillent.
Lesfluxdentre/sortiecin, coutcerret clog sontdclarsdanslespacedenommagestd::
delabibliothquestandardC++.Ondevradoncfaireprcderleurnomduprfixe std:: pour
yaccder,ouutiliserundirective using pourimporterlessymbolesdelabibliothquestandard
C++danslespacedenommageglobal.Voustrouverezdeplusamplesrenseignementssurles
espacesdenommagesdansleChapitre11.

LesavantagesdesfluxC++sontnombreux,onnoteraenparticulierceuxci:

letypedesdonneestautomatiquementprisencompteparlesoprateursdinsertionetdextraction
(ilssontsurchargspourtouslestypesprdfinis);

lesoprateursdextractiontravaillentparrfrence(onnerisqueplusdomettreloprateur&dans
lafonction scanf);

ilestpossiblededfinirdesoprateursdinsertionetdextractionpourdautrestypesdedonnes
quelestypesdebasedulangage;

leurutilisationestglobalementplussimple.

Lesfluxdentre/sortiedfinisparlabibliothqueC++sontdoncduneextrmesouplesseetsont
extensiblesauxtypesdedonnesutilisateur.Parailleurs,ilsdisposentdungrandnombredepara
mtresdeformatageetdoptionsavances.ToutescesfonctionnalitsserontdcritesdansleChapitre
15,onousverronsgalementcommentraliserdesentres/sortiesdansdesfichiers.

8.13.Mthodesvirtuelles
Lesmthodesvirtuellesnontstrictementrienvoiraveclesclassesvirtuelles,bienquellesutilisent
lemmemotcl virtual.Cemotclestutilisicidansuncontexteetdansunsensdiffrent.
Noussavonsquilestpossiblederedfinirlesmthodesduneclassemredansuneclassefille.Lors
delappeldunefonctionainsiredfinie,lafonctionappeleestladernirefonctiondfiniedansla
hirarchiedeclasse. Pourappelerlafonctiondelaclassemrealorsquelleatredfinie, ilfaut
prciserlenomdelaclasselaquelleelleappartientavecloprateurdersolutiondeporte( ::).

135

Chapitre8.C++:lacoucheobjet
Bienquesimple,cetteutilisationdelaredfinitiondesmthodespeutposerdesproblmes.Supposons
quuneclasseBhritedesaclassemreA.SiApossdeunemthode x appelantuneautremthode y
redfiniedanslaclassefilleB,quesepassetillorsquunobjetdeclasseBappellelamthode x ?La
mthodeappeletantcelledelaclasseA,elleappelleralamthodey delaclasseA.Parconsquent,
laredfinitionde y nesertriendsquonlappellepartirdunedesfonctionsdunedesclasses
mres.
Unepremiresolutionconsisteraitredfinirlamthode x danslaclasseB.Maiscenestnilgant,
x delaclasse
niefficace.Ilfautenfaitforcerlecompilateurnepasfaireleliendanslafonction
Aaveclafonction y delaclasseA. Ilfautque x appellesoitlafonction y delaclasseAsielle
estappeleparunobjetdelaclasseA,soitlafonction y delaclasseBsielleestappelepourun
objetdelaclasseB.Lelienaveclunedesmthodes y nedoittrefaitquaumomentdelexcution,
cestdirequondoitfaireuneditiondeliensdynamique.
LeC++permetdefairecela.Pourcela,ilsuffitdedclarervirtuellelafonctiondelaclassedebase
quiestredfiniedanslaclassefille,cestdirelafonction y.Celasefaitenfaisantprcderparle
motcl virtual danslaclassedebase.
Exemple825.Redfinitiondemthodedeclassedebase
#include <iostream>
usingnamespacestd;
//Dfinitlaclassedebasedesdonnes.
classDonneeBase
{
protected:
intNumero;
intValeur;

//Lesdonnessontnumrotes.
//etsontconstituesdunevaleurentire
//pourlesdonnesdebase.

public:
voidEntre(void);
voidMiseAJour(void);
};

//Entreunedonne.
//Metjourladonne.

voidDonneeBase::Entre(void)
{
cin >> Numero;
//Entrelenumrodeladonne.
cout << endl;
cin >> Valeur;
//Entresavaleur.
cout << endl;
return;
}
voidDonneeBase::MiseAJour(void)
{
Entre();
//Entreunenouvelledonne
//laplacedeladonneencours.
return;
}
/*Dfinitlaclassedesdonnesdtailles.*/
classDonneeDetaillee:privateDonneeBase
{

136

Chapitre8.C++:lacoucheobjet
intValeurEtendue;

public:
voidEntre(void);
};

//Lesdonnesdtaillesontenplus
//unevaleurtendue.

//Redfinitiondelamthodedentre.

voidDonneeDetaillee::Entre(void)
{
DonneeBase::Entre();
//Appellelamthodedebase.
cin >> ValeurEtendue; //Entrelavaleurtendue.
cout << endl;
return;
}

Si d estunobjetdelaclasseDonneeDetaillee,lappelde d.Entre necauserapasdeproblme.En


revanche,lappelde d.MiseAJour nefonctionnerapascorrectement,carlafonction Entre appele
dans MiseAJour estlafonctiondelaclasseDonneeBase,etnonlafonctionredfiniedansDonnee
Detaille.
Ilfallaitdclarerlafonction Entre commeunefonctionvirtuelle.Ilnestncessairedelefaireque
danslaclassedebase.Cellecidoitdonctredclarecommesuit:
classDonneeBase
{
protected:
intNumero;
intValeur;
public:
virtualvoidEntre(void);
voidMiseAJour(void);
};

//Fonctionvirtuelle.

Cettefois,lafonction Entre appeledans MiseAJour estsoitlafonctiondelaclasseDonneeBase,


si MiseAJour estappelepourunobjetdeclasseDonneeBase,soitcelledelaclasseDonneeDetaille
si MiseAJour estappelepourunobjetdelaclasseDonneeDetaillee.
Enrsum, lesmthodesvirtuellessont desmthodesqui sont appelesselonlavraieclassede
lobjetquilappelle. Lesobjetsquicontiennentdesmthodesvirtuellespeuventtremanipulsen
tantquobjetsdesclassesdebase,touteneffectuantlesbonnesoprationsenfonctiondeleurtype.
Ilsapparaissentdonccommetantdesobjetsdelaclassedebaseetdesobjetsdeleurclassecomplte
indiffremment,etonpeutlesconsidrersoitcommelesuns,soitcommelesautres.Untelcomporte
mentestappelpolymorphisme(cestdirequipeutavoirplusieursaspectsdiffrents).Nousverrons
uneapplicationdupolymorphismedanslecasdespointeurssurlesobjets.

8.14.Drivation
Nousallonsvoiricilesrglesdedrivation.Cesrglespermettentdesavoircequiestautorisetce
quinelestpaslorsquontravailleavecdesclassesdebaseetleursclassesfilles(ouclassesdrives).
Lapremirergle, quiestaussilaplussimple, indiquequilestpossibledutiliserunobjetdune
classedrivepartout olonpeut utiliserunobjet dunedesesclassesmres. Lesmthodeset

137

Chapitre8.C++:lacoucheobjet
donnesdesclassesmresappartiennenteneffetparhritageauxclassesfilles.Bienentendu,ondoit
avoirlesdroitsdaccssurlesmembresdelaclassedebasequelonutilise(laccspeuttrerestreint
lorsdelhritage).
Ladeuximergleindiquequilestpossibledefaireuneaffectationduneclassedriveversune
classemre.Lesdonnesquineserventpaslinitialisationsontperdues,puisquelaclassemrene
possdepasleschampscorrespondants.Enrevanche,linverseeststrictementinterdit.Eneffet,les
donnesdelaclassefillequinexistentpasdanslaclassemrenepourraientpasrecevoirdevaleur,
etlinitialisationneseferaitpascorrectement.
Enfin,latroisimergleditquelespointeursdesclassesdrivessontcompatiblesaveclespointeurs
desclassesmres.Celasignifiequilestpossibledaffecterunpointeurdeclassedriveunpointeur
dunedesesclassesdebase.Ilfautbienentenduquelonaitenoutreledroitdaccderlaclasse
debase, cestdirequaumoinsundesesmembrespuissetreutilis.
Cetteconditionnestpas
private
toujoursvrifie,enparticulierpourlesclassesdebasedontlhritageest
.
Unobjetdrivpointparunpointeurdunedesclassesmresdesaclasseestconsidrcommeun
objetdelaclassedupointeurquilepointe.Lesdonnesspcifiquessaclassenesontpassupprimes,
ellessontseulementmomentanmentinaccessibles.Cependant,lemcanismedesmthodesvirtuelles
continuedefonctionnercorrectement. Enparticulier, ledestructeurdelaclassedebasedoit tre
dclarentantquemthodevirtuelle.Celapermetdappelerlebondestructeurencasdedestruction
delobjet.
Ilestpossibledeconvertirunpointeurdeclassedebaseenunpointeurdeclassedrivesilaclasse
debasenestpasvirtuelle. Cependant, mmelorsquelaclassedebasenestpasvirtuelle, celaest
dangereux, carlaclassedrivepeutavoirdesmembresquinesontpasprsentsdanslaclassede
base, etlutilisationdecepointeurpeutconduiredeserreurstrsgraves.
Cestpourcetteraison
quuntranstypageestncessairepourcetypedeconversion.
Soientparexemplelesdeuxclassesdfiniescommesuit:
#include <iostream>
usingnamespacestd;
classMere
{
public:
Mere(void);
~Mere(void);
};
Mere::Mere(void)
{
cout << "Constructeurdelaclassemre."<< endl;
return;
}
Mere::~Mere(void)
{
cout << "Destructeurdelaclassemre."<< endl;
return;
}
classFille:publicMere
{
public:

138

Chapitre8.C++:lacoucheobjet
Fille(void);
~Fille(void);
};
Fille::Fille(void):Mere()
{
cout << "Constructeurdelaclassefille."<< endl;
return;
}
Fille::~Fille(void)
{
cout << "Destructeurdelaclassefille."<< endl;
return;
}

Aveccesdfinitions,seulelapremiredesdeuxaffectationssuivantesestautorise:
Merem;
Fillef;

//Instanciationdedeuxobjets.

m=f;
f=m;

//Celaestautoris,maislinverseneleseraitpas:
//ERREUR!!(necompilepas).

Lesmmesrglessontapplicablespourlespointeursdobjets:
Mere*pm,m;
Fille*pf,f;
pf=&f;
//Autoris.
pm=pf;
//Autoris.Lesdonnesetlesmthodes
//delaclassefillenesontplusaccessibles
//aveccepointeur:*pmestunobjet
//delaclassemre.
pf=&m;
//ILLGAL:ilfautfaireuntranstypage:
pf=(Fille*)&m; //Cettefois,cestlgal,maisDANGEREUX!
//Eneffet,lesmthodesdelaclassefilles
//nesontpasdfinies,puisquemestuneclassemre.

Lutilisationdunpointeursurlaclassedebasepouraccderuneclassedrivencessitedutiliser
desmthodesvirtuelles. Enparticulier, il est ncessairederendrevirtuelslesdestructeurs.
Par
exemple,avecladfinitiondonnecidessuspourlesdeuxclasses,lecodesuivantestfaux:
Mere*pm;
Fille*pf=newFille;
pm=pf;
deletepm;//Appeldudestructeurdelaclassemre!

Pourrsoudreleproblme, ilfautqueledestructeurdelaclassemresoitvirtuel(ilestinutilede
dclarervirtuelledestructeurdesclassesfilles):

139

Chapitre8.C++:lacoucheobjet
classMere
{
public:
Mere(void);
virtual~Mere(void);
};

Onnoteraquebienqueloprateur delete soitunefonctionstatique,lebondestructeurestappe


l, carledestructeurestdclar virtual. Eneffet, loprateur delete rechercheledestructeur
appelerdanslaclassedelobjetleplusdriv.Deplus,loprateur delete restituelammoirede
lobjetcomplet,etpasseulementcelledusousobjetrfrencparlepointeurutilisdanslexpression
delete.Lorsquonutiliseladrivation,ilestdonctrsimportantdedclarerlesdestructeursvirtuels
pourqueloprateur delete utiliselevraitypedelobjetdtruire.

8.15.MthodesvirtuellespuresClassesabstraites
Unemthodevirtuellepureestunemthodequiestdclaremaisnondfiniedansuneclasse.Elle
estdfiniedansunedesclassesdrivesdecetteclasse.
Uneclasseabstraiteestuneclassecomportantaumoinsunemthodevirtuellepure.
tantdonnquelesclassesabstraitesontdesmthodesnondfinies,ilestimpossibledinstancierdes
objetspourcesclasses.Enrevanche,onpourralesrfrenceravecdespointeurs.
Lemcanismedesmthodesvirtuellespuresetdesclassesabstraitespermetdecrerdesclassesde
basecontenanttouteslescaractristiquesdunensembledeclassesdrives,pourpouvoirlesmanipu
leravecununiquetypedepointeur.Eneffet,lespointeursdesclassesdrivessontcompatiblesavec
lespointeursdesclassesdebase,onpourradoncrfrencerlesclassesdrivesavecdespointeurs
surlesclassesdebase,doncavecununiquetypesousjacent:celuidelaclassedebase.Cependant,
lesmthodesdesclassesdrivesdoiventexisterdanslaclassedebasepourpouvoirtreaccessibles
traverslepointeursurlaclassedebase. Cesticiquelesmthodesvirtuellespuresapparaissent.
Ellesformentunmoulepourlesmthodesdesclassesdrives,quilesdfinissent.Bienentendu,il
fautquecesmthodessoientdclaresvirtuelles,puisquelaccssefaitavecunpointeurdeclassede
baseetquilfautquecesoitlamthodedelaclasserelledelobjet(cestdirelaclassedrive)
quisoitappele.
Pourdclarerunemthodevirtuellepuredansuneclasse, ilsuffitdefairesuivresadclarationde
=0 .Lafonctiondoitgalementtredclarevirtuelle:
virtualtypenom(paramtres)=0;
=0 signifieicisimplementquilnyapasdimplmentationdecettemthodedanscetteclasse.
Note: =0 doittreplaccompltementenfindedclaration,cestdireaprslemotcl const
pourlesmthodes const et aprsladclarationdelalistedesexceptionsautorises(voirle
Chapitre9pourplusdedtailscesujet).

Unexemplevautmieuxquunlongdiscours.Soitdonc,parexemple,construireunestructurede
donnespouvantcontenirdautresstructuresdedonnes,quelsquesoientleurstypes.Cettestructure
dedonnesestappeleunconteneur,parcequellecontientdautresstructuresdedonnes.Ilestpos

140

Chapitre8.C++:lacoucheobjet
siblededfinirdiffrentstypesdeconteneurs.Danscetexemple,onnesintresseraquauconteneur
detypesac.
Unsacestunconteneurpouvantcontenirzroouplusieursobjets,chaqueobjetntantpasforcment
unique. Unobjetpeutdonctreplacplusieursfoisdanslesac. Unsacdisposededeuxfonctions
permettantdymettreetdenretirerunobjet.Ilaaussiunefonctionpermettantdediresiunobjetse
trouvedanslesac.
Nousallonsdclareruneclasseabstraitequiserviradeclassedebasepourtouslesobjetsutilisables.
Lesacnemanipuleraquedespointeurssurlaclasseabstraite,cequipermettrasonutilisationpour
touteclassedrivantdecetteclasse.Afindediffrencierdeuxobjetsgaux,unnumrouniquedevra
treattribuchaqueobjetmanipul. Lechoixdecenumroestlachargedesobjets, laclasse
abstraitedontilsdriventdevradoncavoirunemthoderenvoyantcenumro.
Lesobjetsdevront
touspouvoirtreaffichsdansunformatquileurestpropre. Lafonctionutiliserpourcelasera
print.Cettefonctionseraunemthodevirtuellepuredelaclasseabstraite,puisquelledevratre
dfiniepourchaqueobjet.
Passonsmaintenantauprogramme...
Exemple826.Conteneurdobjetspolymorphiques
#include <iostream>
usingnamespacestd;
/*************

LACLASSEABSTRAITEDEBASE

*****************/

classObject
{
unsignedlongintnew_handle(void);
protected:
unsignedlonginth;

//Identifiantdelobjet.

public:
Object(void);
//Leconstructeur.
virtual~Object(void);
//Ledestructeurvirtuel.
virtualvoidprint(void)=0;//Fonctionvirtuellepure.
unsignedlonginthandle(void)const; //Fonctionrenvoyant
//lenumrodidentification
//delobjet.
};
//CettefonctionnestappelablequeparlaclasseObject:
unsignedlongintObject::new_handle(void)
{
staticunsignedlonginthc=0;
returnhc=hc+1;
//hcestlidentifiantcourant.
//Ilestincrment
}
//chaqueappeldenew_handle.
//LeconstructeurdeObjectdoittreappelparlesclassesdrives:
Object::Object(void)
{
h=new_handle();

//Trouveunnouvelidentifiant.

141

Chapitre8.C++:lacoucheobjet
return;
}
Object::~Object(void)
{
return;
}
unsignedlongintObject::handle(void)const
{
returnh;
//Renvoielenumrodelobjet.
}
/********************LACLASSESAC
classBag:publicObject

******************/

//Laclassesac.Ellehrite
//deObject,carunsacpeut
//encontenirunautre.Lesac
//estimplmentsouslaforme
//dunelistechane.

{
structBagList
{
BagList*next;
Object *ptr;
};
BagList*head;

//Lattedeliste.

public:
Bag(void);
//Leconstructeur:appelceluideObject.
~Bag(void);
//Ledestructeur.
voidprint(void);//Fonctiondaffichagedusac.
boolhas(unsignedlongint)const;
//truesilesaccontientlobjet.
boolis_empty(void)const; //truesilesacestvide.
voidadd(Object&);
//Ajouteunobjet.
voidremove(Object&);
//Retireunobjet.
};
Bag::Bag(void):Object()
{
return; //NefaitriendautrequappelerObject::Object().
}
Bag::~Bag(void)
{
BagList*tmp=head;
while(tmp!=NULL)
{
tmp=tmp>next;
deletehead;
head=tmp;
}
return;
}

142

//Dtruitlalistedobjet.

Chapitre8.C++:lacoucheobjet
voidBag::print(void)
{
BagList*tmp=head;
cout << "Sacn " << handle() << "." << endl;
cout << "
Contenu:" << endl;
while(tmp!=NULL)
{
cout << "\t";
tmp>ptr>print();
tmp=tmp>next;
}
return;

//Indentelasortiedesobjets.
//Affichelalisteobjets.

}
boolBag::has(unsignedlonginth)const
{
BagList*tmp=head;
while(tmp!=NULL&&tmp>ptr>handle()!=h)
tmp=tmp>next;
//Cherchelobjet.
return(tmp!=NULL);
}
boolBag::is_empty(void)const
{
return(head==NULL);
}
voidBag::add(Object&o)
{
BagList*tmp=newBagList;
tmp>ptr=&o;
tmp>next=head;
head=tmp;
return;
}

//Ajouteunobjetlaliste.

voidBag::remove(Object&o)
{
BagList*tmp1=head,*tmp2=NULL;
while(tmp1!=NULL&&tmp1 >ptr>handle()!=o.handle())
{
tmp2=tmp1;
//Cherchelobjet...
tmp1=tmp1 >next;
}
if(tmp1!=NULL)
//etlesupprimedelaliste.
{
if(tmp2!=NULL)tmp2>next=tmp1>next;
elsehead=tmp1 >next;
deletetmp1;
}
return;
}

AveclaclasseBagdfinietellequelle,ilestprsentpossibledestockerdesobjetsdrivantdela
classeObjectaveclesfonctions add et remove :

143

Chapitre8.C++:lacoucheobjet
classMonObjet:publicObject
{
/* Dfinirlamthodeprint()pourlobjet...
};

*/

BagMonSac;
intmain(void)
{
MonObjeta,b,c;
MonSac.add(a);
MonSac.add(b);
MonSac.add(c);
MonSac.print();
MonSac.remove(b);
MonSac.add(MonSac);
MonSac.print();

//Effectuequelquesoprations
//aveclesac:

//Unsacpeutcontenirunsac!
//Attention!Cetappelestrcursif!
//(plantageassur).

return0;
}

Nousavonsvuquelaclassedebaseservaitdemouleauxclassesdrives.Ledroitdempcherune
fonctionmembrevirtuellepuredfiniedansuneclassedrivedaccderencriturenonseulement
auxdonnesdelaclassedebase,maisaussiauxdonnesdelaclassedrive,peutdoncfairepartie
desesprrogatives.Celaestfaisableendclarantlepointeur this commetantunpointeurconstant
surobjetconstant. Nousavonsvuquecelapouvaitsefaireenrajoutantlemotcl const aprsla
dclarationdelafonctionmembre.Parexemple,commelidentifiantdelobjetdebaseestplacen
protected aulieudtreen private,laclasseObjectautorisesesclassesdriveslemodifier.
Cependant,ellepeutempcherlafonction print delemodifierenladclarant const :
classObject
{
unsignedlongintnew_handle(void);
protected:
unsignedlonginth;
public:
Object(void);
//Leconstructeur.
virtualvoidprint(void)const=0; //Fonctionvirtuellepure.
unsignedlonginthandle(void)const;//Fonctionrenvoyant
//lenumrodidentification
//delobjet.
};

Danslexempledonncidessus,lafonctionprint peutaccderenlecture h,maisplusencriture.


Enrevanche,lesautresfonctionsmembresdesclassesdrivespeuventyavoiraccs,puisquecest
unedonnemembre protected.Cettemthodedencapsulationestdonccooprative(ellerequiert
labonnevolontdesautresfonctionsmembresdesclassesdrives), tout commelamthodequi
consistaitenCdclarerunevariableconstante.Cependant,ellepermettradedtecterdesanomalies
lacompilation,carsiunefonction print cherchemodifierlobjetsurlequelelletravaille,ilya
manifestementuneerreurdeconception.

144

Chapitre8.C++:lacoucheobjet
Bienentendu,celafonctionnegalementaveclesfonctionsmembresvirtuellesnonpures,etmme
aveclesfonctionsnonvirtuelles.

8.16.Pointeurssurlesmembresduneclasse
Nousavonsdjvulespointeurssurlesobjets.Ilnousrestevoirlespointeurssurlesmembresdes
classes.
Lesclassesregroupentlescaractristiquesdesdonnesetdesfonctionsdesobjets.Lesmembresdes
classesnepeuventdoncpastremanipulssanspasserparlaclasselaquelleilsappartiennent.Par
consquent,ilfaut,lorsquonveutfaireunpointeursurunmembre,indiquerlenomdesaclasse.Pour
cela,lasyntaxesuivanteestutilise:
dfinitionclasse::*pointeur

Parexemple,siuneclassetestcontientdesentiers,letypedepointeursutiliserpourstockerleur
adresseest:
inttest::*

Sionveutdclarerunpointeur p decetype,oncriradonc:
inttest::*p1;

//Construitlepointeursurentier
//delaclassetest.

Unefoislepointeurdclar,onpourralinitialiserenprenantladressedumembredelaclassedutype
correspondant.Pourcela,ilfaudraencorespcifierlenomdelaclasseavecloprateurdersolution
deporte:
p1=&test::i;

//Rcupreladressedei.

Lammesyntaxeestutilisablepourlesfonctions.Lemploidun typedef estdanscecasfortement


recommand.Parexemple,silaclassetestdisposedunefonctionmembreappelelit,quinattend
aucunparamtreetquirenvoieunentier,onpourrarcuprersonadresseainsi:
typedefint(test::*pf)(void); //Dfinitletypedepointeur.
pfp2=&test::lit;
//Construitlepointeuret
//litladressedelafonction.

Cependant,cespointeursnesontpasutilisablesdirectement.Eneffet,lesdonnesduneclassesont
instanciespourchaqueobjet,etlesfonctionsmembresreoiventsystmatiquementlepointeurthis
surlobjetdemanireimplicite.Onnepeutdoncpasfaireundrfrencementdirectdecespointeurs.
Ilfautspcifierlobjetpourlequellepointeurvatreutilis.Celasefaitaveclasyntaxesuivante:
objet.*pointeur

145

Chapitre8.C++:lacoucheobjet

Pourlespointeursdobjet, onpourrautiliserloprateur >* laplacedeloprateur .* (appel


pointeursuroprateurdeslectiondemembre).
Ainsi,si a estunobjetdeclassetest,onpourraaccderladonne i decetobjettraverslepointeur
p1 aveclasyntaxesuivante:
a.*p1=3;

//Initialiseladonnemembreideaaveclavaleur3.

Pourlesfonctionsmembres,onmettradesparenthsescausedesprioritsdesoprateurs:
inti=(a.*p2)();

//Appellelafonctionlit()pourlobjeta.

Pourlesdonnesetlesfonctionsmembresstatiques, cependant, lasyntaxeestdiffrente. Eneffet,


lesdonnesnappartiennentplusauxobjetsdelaclasse,maislaclasseellemme,etilnestplus
ncessairedeconnatrelobjetauquellepointeursappliquepourlesutiliser.Demme,lesfonctions
membresstatiquesnereoiventpaslepointeursurlobjet,etonpeutdonclesappelersansrfrencer
cedernier.
Lasyntaxesentrouvedoncmodifie.Lespointeurssurlesmembresstatiquesdesclassessontcom
patiblesaveclespointeurssurlesobjetsetlesfonctionsnonmembres.Parconsquent,siuneclasse
contientunedonnestatiqueentire,onpourrarcuprersonadressedirectementetlamettredansun
pointeurdentier:
int*p3=&test::entier_statique;

//Rcupreladresse
//deladonnemembre
//statique.

Lammesyntaxesappliquerapourlesfonctions:
typedefint(*pg)(void);
pgp4=&test::fonction_statique;

//Rcupreladresse
//dunefonctionmembre
//statique.

Enfin, lutilisationdescespointeursest identiquecelledespointeursclassiques, puisquil nest


pasncessairedefournirlepointeur this.Ilestdoncimpossibledespcifierlepointeursurlobjet
surlequellafonctiondoittravaillerauxfonctionsmembresstatiques. Celaestnaturel, puisqueles
fonctionsmembresstatiquesnepeuventpasaccderauxdonnesnonstatiquesduneclasse.
Exemple827.Pointeurssurmembresstatiques
#include <iostream>
usingnamespacestd;
classtest
{
inti;

146

Chapitre8.C++:lacoucheobjet
staticintj;
public:
test(intj)
{
i=j;
return;
}
staticintget(void)
{
/*returni;
INTERDIT:iestnonstatique
etgetlest!*/
returnj;//Autoris.
}
};
inttest::j=5;

//Initialiselavariablestatique.

typedefint(*pf)(void);

//Pointeurdefonctionrenvoyant
//unentier.
//Initialisationlicite,carget
//eststatique.

pfp=&test::get;

intmain(void)
{
cout << (*p)() << endl;//Affiche5.Onnespcifiepaslobjet.
return0;
}

147

Chapitre8.C++:lacoucheobjet

148

Chapitre9.LesexceptionsenC++
Uneexceptionestlinterruptiondelexcutionduprogrammelasuitedunvnementparticulier.Le
butdesexceptionsestderaliserdestraitementsspcifiquesauxvnementsquiensontlacause.Ces
traitementspeuventrtablirleprogrammedanssonmodedefonctionnementnormal,auquelcasson
excutionreprend.Ilsepeutaussiqueleprogrammesetermine,siaucuntraitementnestappropri.
LeC++supportelesexceptionslogicielles,dontlebutestdegrerleserreursquisurviennentlors
delexcutiondesprogrammes.Lorsquunetelleerreursurvient,leprogrammedoitlanceruneex
ception. Lexcutionnormaleduprogrammesarrtedsquelexceptionestlance, etlecontrle
estpassungestionnairedexception.Lorsquungestionnairedexceptionsexcute,onditquila
attraplexception.
Lesexceptionspermettentunegestionsimplifiedeserreurs,parcequellesenreportentletraitement.
Lecodepeutalorstrecritsanssesoucierdescasparticuliers,cequilesimplifiegrandement.Les
casparticulierssonttraitsdanslesgestionnairesdexception.
Engnral, unefonctionquidtecteuneerreurdexcutionnepeutpasseterminernormalement.
Commesontraitementnapaspusedroulernormalement, ilestprobablequelafonctionquila
appeleconsidreelleaussiquuneerreuraeulieuetterminesonexcution.Lerreurremonteainsila
listedesappelantsdelafonctionquiagnrlerreur.Ceprocessuscontinue,defonctionenfonction,
jusqucequelerreursoitcompltementgreoujusqucequeleprogrammesetermine(cecas
survientlorsquelafonctionprincipalenepeutpasgrerlerreur).
Traditionnellement,cemcanismeestimplmentlaidedecodesderetourdesfonctions.Chaque
fonctiondoitrenvoyerunevaleurspcifiquelissuedesonexcution,permettantdindiquersielle
sestcorrectementdrouleounon. Lavaleurrenvoyeestdoncutiliseparlappelantpourdter
minerlanaturedelerreur,et,sierreurilya,prendrelesmesuresncessaires.Cettemthodeper
metchaquefonctiondelibrerlesressourcesquelleaalloueslorsdelaremontedeserreurs,et
deffectuerainsisapartdutraitementderreur.
Malheureusement,cettetechniquencessitedetesterlescodesderetourdechaquefonctionappele,
etlalogiquederreurdveloppefinitpardevenirtrslourde,puisquecestestssimbriquentlesuns
lasuitedesautreset quelecodedutraitement deserreurssetrouvemlangaveclecodedu
fonctionnementnormaldelalgorithme.Cettecomplicationpeutdeveniringrablelorsqueplusieurs
valeursdecodesderetourpeuventtrerenvoyesafindedistinguerlesdiffrentscasderreurpossible,
caril peut endcoulerungrandnombredetestset beaucoupdecasparticuliersgrerdansles
fonctionsappelantes.
Certainsprogrammesutilisentdoncunesolutionastucieuse,quiconsistedporterletraitementdes
erreurseffectuerendehorsdelalgorithmepardessautsverslafindelafonction.Lecodedenet
toyage,quisetrouvealorsaprslalgorithme,estexcutcompltementsitoutsepassecorrectement.
Enrevanche,silamoindreerreurestdtecteencoursdexcution,unsautestralisverslapartie
ducodedenettoyagecorrespondanteautraitementquiadjteffectu.Ainsi,cecodenestcrit
quuneseulefois,etletraitementdeserreursestsituendehorsdutraitementnormal.
Lasolutionprcdenteesttoutfaitvalable(enfait,cestmmelasolutionlaplussimple),maiselle
souffreduninconvnient.Ellerendleprogrammemoinsstructur,cartouteslesressourcesutilises
parlalgorithmedoivent treaccessiblesdepuislecodedetraitement
deserreurs. Cesressources
doiventdonctreplacesdansuneporterelativementglobale,voiredclaresenttedefonction.De
plus,letraitementdescodesderreursmultiplesposetoujourslesmmesproblmesdecomplication
destests.
Lasolutionquimetenoeuvrelesexceptionsestbeaucoupplussimple,puisquelafonctionquidtecte
uneerreurpeutsecontenterdelanceruneexception. Cetteexceptioninterromptlexcutiondela
fonction, etungestionnairedexceptionappropriestrecherch. Larecherchedugestionnairesuit

149

Chapitre9.LesexceptionsenC++
lemmecheminquecelui utilislorsdelaremontedeserreurs:
savoirlalistedesappelants.
Lapremirefonctionappelantequi contient ungestionnairedexceptionappropriprenddoncle
contrle, et effectueletraitement delerreur. Si letraitement est complet, leprogrammereprend
sonexcutionnormale. Danslecascontraire, legestionnairedexceptionpeutrelancerlexception
(auquelcaslegestionnairedexceptionsuivantestrecherch)outerminerleprogramme.
LemcanismedesexceptionsduC++garantitquetouslesobjetsdeclassedestockageautomatique
sontdtruitslorsquelexceptionquiremontesortdeleurporte.Ainsi,sitouteslesressourcessont
encapsulesdansdesclassesdisposantdundestructeurcapabledelesdtruireoudelesramener
dansuntat cohrent, laremontedesexceptionseffectueautomatiquement lemnage. Deplus,
lesexceptionspeuventtretypes, etcaractriserainsilanaturedelerreurquisestproduite. Ce
mcanismeestdoncstrictementquivalententermesdefonctionnalitsauxcodesderreursutiliss
prcdemment.
Commeonlevoit, lesexceptionspermettent desimplifier lecode, enreportant endehorsde
lalgorithmenormalletraitementdeserreurs.Parailleurs,lalogiquederreurestcompltementprise
enchargeparlelangage,etleprogrammeurnaplusfairelestestsquipermettentdedterminerle
traitementappropripourchaquetypederreur.LesmcanismesdegestiondesexceptionsduC++
sontdcritsdanslesparagraphessuivants.

9.1.Lancementetrcuprationduneexception
EnC++, lorsquilfautlanceruneexception, ondoitcrerunobjetdontlaclassecaractrisecette
exception,etutiliserlemotcl throw.Sasyntaxeestlasuivante:
throwobjet;

o objet estlobjetcorrespondantlexception.Cetobjetpeuttredenimportequeltype,etpourra
ainsicaractriserpleinementlexception.
Lexceptiondoitalorstretraiteparlegestionnairedexceptioncorrespondant.Onnepeutattraper
quelesexceptionsquisontapparuesdansunezonedecodelimite(cettezoneestditeprotgecontre
leserreursdexcution),passurtoutunprogramme.Ondoitdoncplacerlecodesusceptibledelancer
uneexceptiondunblocdinstructionsparticulier.Ceblocestintroduitaveclemotcltry :
try
{
//Codesusceptibledegnrerdesexceptions...
}

Lesgestionnairesdexceptionsdoiventsuivrelebloc try.Ilssontintroduitsaveclemotcl catch :


catch(classe[&][temp])
{
//Traitementdelexceptionassocielaclasse
}

Notezquelesobjetsdeclassedestockageautomatiquedfinisdanslebloctry sontautomatiquement
dtruitslorsquuneexceptionfaitsortirlecontrleduprogrammedeleurporte.
Cestgalement
lecasdelobjet construit pourlancerlexception. Lecompilateureffectuedoncunecopiedecet
objetpourletransfreraupremierbloc catch capabledelerecevoir. Celaimpliquequilyaitun
constructeurdecopiepourlesclassesdexceptionsnontriviales.

150

Chapitre9.LesexceptionsenC++
Demme,lesblocs catch peuventrecevoirleursparamtresparvaleurouparrfrence,commele
montrelasyntaxeindiquecidessus.Engnral,ilestprfrabledutiliserunerfrence,afindviter
unenouvellecopiedelobjetdelexceptionpourlebloc catch.Toutefois,onprendragardeaufait
quedanscecas,lesmodificationseffectuessurleparamtreseronteffectuesdanslacopiedetravail
ducompilateuretserontdoncgalementvisiblesdanslesblocs catch desfonctionsappelantesou
deportesuprieure,silexceptionestrelanceaprstraitement.
Ilpeutyavoirplusieursgestionnairesdexceptions.Chacuntraiteralesexceptionsquionttgnres
danslebloc try etdontlobjetestdelaclasseindiqueparsonparamtre.Ilnestpasncessairede
donnerunnomlobjet( temp)danslexpression catch.Cependant,celapermetdelercuprer,ce
quipeuttrencessairesilondoitrcuprerdesinformationssurlanaturedelerreur.
Enfin, ilestpossiblededfinirungestionnairedexceptionuniversel, quircupreratouteslesex
ceptionspossibles, quelsquesoient leurstypes. Cegestionnairedexceptiondoit prendrecomme
paramtretroispointsdesuspensionentreparenthsesdanssaclause catch.Bienentendu,dansce
cas,ilestimpossibledespcifierunevariablequicontientlexception,puisquesontypeestindfini.
Exemple91.Utilisationdesexceptions
#include <iostream>
usingnamespacestd;
classerreur

//Premireexceptionpossible,associe
//lobjeterreur.

{
public:
intcause; //Entierspcifiantlacausedelexception.
//Leconstructeur.Ilappelleleconstructeurdecause.
erreur(intc):cause(c){}
//Leconstructeurdecopie.Ilestutilisparlemcanisme
//desexceptions:
erreur(consterreur&source):cause(source.cause){}
};
classother{};

//Objetcorrespondanttoutes
//lesautresexceptions.

intmain(void)
{
inti;
//Typedelexceptiongnrer.
cout << "Tapez0pourgnreruneexceptionErreur,"
"1pouruneEntire:";
cin >> i;
//Onvagnrerunedestroisexceptions
//possibles.
cout << endl;
try
//Blocolesexceptionssontprisesencharge.
{
switch(i)
//Selonletypedexceptiondsire,
{
case0:
{
erreura(0);
throw(a);
//onlancelobjetcorrespondant
//(ici,declasseerreur).
//Celainterromptlecode.breakest
//doncinutileici.

151

Chapitre9.LesexceptionsenC++
}
case1:
{
inta=1;
throw(a);

//Exceptiondetypeentier.
}
default:
//Silutilisateurnapastap0ou1,
{
otherc;
//oncrelobjetc(typedexception
throw(c);
//other)etonlelance.
}
}
}
//findubloctry.Lesblocscatchsuivent:
catch(erreur&tmp)//Traitementdelexceptionerreur...
{
//(avecrcuprationdelacause).
cout << "Erreurerreur!(cause" << tmp.cause << ")" << endl;
}
catch(inttmp)
//Traitementdelexceptionint...
{
cout << "Erreurint!(cause"
<< tmp << ")" << endl;
}
catch(...)
//Traitementdetouteslesautres
{
//exceptions(...).
//Onnepeutpasrcuprerlobjetici.
cout << "Exceptioninattendue!" << endl;
}
return0;
}

Seloncequentrelutilisateur,uneexceptiondutypeerreur,intouotherestgnre.

9.2.Remontedesexceptions
Lesfonctionsintressesparlesexceptionsdoivent
lescapteraveclemot cl catch commeon
lavucidessus.EllespeuventalorseffectuertouslestraitementsderreursqueleC++neferapas
automatiquement.Cestraitementscomprennentgnralementlertablissementdeltatdesdonnes
manipulesparlafonction(dont,pourlesfonctionsmembresduneclasse,lesdonnesmembresde
lobjetcourant),ainsiquelalibrationdesressourcesnonencapsulesdansdesobjetsdeclassede
stockageautomatique(parexemple,lesfichiersouverts,lesconnexionsrseau,etc.).
Unefoiscetravaileffectu,ellespeuvent,siellesledsirent,relancerlexception,afindepermettre
untraitementcomplmentaireparleurfonctionappelante.Leparcoursdelexceptionsarrteradonc
dsquelerreurauratcompltementtraite.Bienentendu,ilestgalementpossibledelancerune
autreexceptionquecellequelonareue,commecepeuttreparexemplelecassiletraitementde
lerreurprovoqueluimmeuneerreur.
Pourrelancerlexceptionencoursdetraitementdansungestionnairedexception,ilfaututiliserle
motcl throw.Lasyntaxeestlasuivante:
throw;

Lexceptionestalorsrelance,aveccommevaleurlobjetquelecompilateuraconstruiteninterne
pourpropagerlexception.Lesgestionnairesdexceptionpeuventdoncmodifierlesparamtresdes
exceptions,silslesattrapentavecunerfrence.

152

Chapitre9.LesexceptionsenC++
Si, lorsquuneexceptionseproduit dansunbloc try, il est impossibledetrouverlebloc catch
correspondantlaclassedecetteexception, ilseproduituneerreurdexcution. Lafonctionpr
dfinie std::terminate estalorsappele. Ellesecontentedappelerunefonctiondetraitement
delerreur, quiellemmeappellelafonction abort delabibliothqueC. Cettefonctiontermine
encatastrophelexcutionduprogrammefautifengnrantunefaute(lesressourcesallouesparle
programmenesontdoncpaslibres,etdesdonnespeuventtreperdues).Cenestgnralement
paslecomportementdsir,aussiestilpossibledelemodifierenchangeantlafonctionappelepar
std::terminate.
Pourcela, ilfaututiliserlafonction std::set_terminate, quiattendenparamtreunpointeur
surlafonctiondetraitementderreur,quineprendaucunparamtreetrenvoievoid.Lavaleurren
voyepar std::set_terminate estlepointeursurlafonctiondetraitementderreurprcdente.
std::terminate et std::set_terminate sontdclareedanslefichierdentte exception.
Note:Commeleursnomslindiquent, std::terminate et std::set_terminate sontdclares
danslespacedenommagestd::,quiestrservpourtouslesobjetsdelabibliothquestandard
std:: devantcesnoms,
C++.Sivousnevoulezpasavoirutilisersystmatiquementleprfixe
vousdevrezajouterlaligne usingnamespacestd; aprsavoirincluslentteexception .
VousobtiendrezdeplusamplesrenseignementssurlesespacesdenommagedansleChapitre
11.

Exemple92.Installationdungestionnairedexceptionavecset_terminate
#include <iostream>
#include <exception>
usingnamespacestd;
voidmon_gestionnaire(void)
{
cout << "Exceptionnongrereue!" << endl;
cout << "Jetermineleprogrammeproprement..."
<< endl;
exit(1);
}
intlance_exception(void)
{
throw2;
}
intmain(void)
{
set_terminate(&mon_gestionnaire);
try
{
lance_exception();
}
catch(doubled)
{
cout << "Exceptiondetypedoublereue:" <<
d << endl;
}
return0;

153

Chapitre9.LesexceptionsenC++
}

9.3.Listedesexceptionsautorisespourunefonction
Ilestpossibledespcifierlesexceptionsquipeuventtrelancesparunefonction.Pourcela,ilfaut
fairesuivresonenttedumotcl throw avec, entreparenthsesetsparespardesvirgules, les
classesdesexceptionsquelleestautoriselancer.Parexemple,lafonctionsuivante:
intfonction_sensible(void)
throw(int,double,erreur)
{
...
}

naledroitdelancerquedesexceptionsdutypeint,doubleouerreur.Siuneexceptiondunautre
typeestlance,parexempleuneexceptiondutypechar*,ilseproduitencoreunefoisuneerreur
lexcution.
Enfait, lafonction std::unexpected est appele. Cettefonctionsecomportedemanire
similaire std::terminate,puisquelleappellepardfautunefonctiondetraitementdelerreur
qui ellemmeappellelafonction std::terminate (et donc abort enfindecompte). Cela
conduit laterminaisonduprogramme. Onpeut encoreunefoischangercecomportement par
dfautenremplaantlafonctionappelepar std::unexpected paruneautrefonctionlaidede
std::set_unexpected, qui est dclaredanslefichier dentte exception. Cettedernire
attendenparamtreunpointeursurlafonctiondetraitement derreur, qui nedoit prendreaucun
paramtreetquinedoitrienrenvoyer. std::set_unexpected renvoielepointeursurlafonction
detraitementderreurprcdemmentappelepar std::unexpected.
Note: Commeleurs noms lindiquent, std::unexpected et std::set_unexpected sont
dclaresdanslespacedenommage std::,qui estrservpourlesobjetsdelabibliothque
standardC++.Sivousnevoulezpasavoirutilisersystmatiquementleprfixe std:: pources
noms, vousdevrezajouter laligne usingnamespacestd; aprsavoir incluslentte
exception. Vousobtiendrezdeplusamplesrenseignementssur lesespacesdenommage
dansleChapitre11.

Ilestpossiblederelanceruneautreexceptionlintrieurdelafonctiondetraitementderreur.Sicette
exceptionsatisfaitlalistedesexceptionsautorises, leprogrammereprendsoncoursnormalement
danslegestionnairecorrespondant.Cestgnralementcequeloncherchefaire.Legestionnaire
peutgalementlanceruneexceptiondetypestd::bad_exception,dclarecommesuitdanslefichier
dentte exception :
classbad_exception:publicexception
{
public:
bad_exception(void)throw();
bad_exception(constbad_exception&)throw();
bad_exception&operator=(constbad_exception&)throw();
virtual~bad_exception(void)throw();
virtualconstchar*what(void)constthrow();
};

154

Chapitre9.LesexceptionsenC++
Celaapourconsquencedeterminerleprogramme.
Enfin, le gestionnaire dexceptions nonautorises peut directement mettre fin lexcution
duprogrammeenappelant std::terminate. Cest lecomportement utilispar lafonction
std::unexpected dfiniepardfaut.
Exemple93.Gestiondelalistedesexceptionsautorises
#include <iostream>
#include <exception>
usingnamespacestd;
voidmon_gestionnaire(void)
{
cout << "Uneexceptionillgaleatlance."<< endl;
cout << "Jerelanceuneexceptiondetypeint."<< endl;
throw2;
}
intf(void)throw(int)
{
throw"5.35";
}
intmain(void)
{
set_unexpected(&mon_gestionnaire);
try
{
f();
}
catch(inti)
{
cout << "Exceptiondetypeintreue:" <<
i << endl;
}
return0;
}
Note:Lalistedesexceptionsautorisesdansunefonctionnefaitpaspartiedesasignature.
Ellenintervientdoncpasdanslesmcanismesdesurchargedesfonctions.Deplus,elledoitse
placeraprslemotcl const danslesdclarationsdefonctionsmembres const (enrevanche,
elledoitseplaceravant =0 danslesdclarationsdesfonctionsvirtuellespures).
Onprendragardeaufaitquelesexceptionsnesontpasgnresparlemcanismedegestion
deserreursduC++(niduC).Celasignifiequepouravoiruneexception,ilfautlalancer,lecom
pilateurneferapaslestestspourvous(testsdedbordementsnumriquesdanslescalculspar
exemple).Celasupposeraitdeprdfinirunensembledeclassespourleserreursgnriques.
Lestestsdevaliditduneoprationdoivent donctrefaitsmalgrtout et, lecaschant, il
fautlanceruneexceptionpourreporterletraitementencasdchec.Demme,lesexceptions
gnresparlamachinehteduprogrammenesontengnral pasrcupresparlesimpl
mentationset,sielleslesont,lesprogrammesquilesutilisentnesontpasportables.

155

Chapitre9.LesexceptionsenC++

9.4.Hirarchiedesexceptions
LemcanismedesexceptionsduC++sebasesurletypagedesobjets,puisquelelancementdune
exceptionncessitelaconstructiondunobjetquilacaractrise,etlebloc catch destinationdecette
exceptionseraslectionnenfonctiondutypedecetobjet.Bienentendu,lesobjetsutilisspourlancer
lesexceptionspeuventcontenirdesinformationsconcernantlanaturedeserreursquiseproduisent,
maisilestgalementpossibledeclassifierceserreursparcatgoriesensebasantsurleurstypes.
Eneffet,lesobjetsexceptionspeuventtredesinstancesdeclassesdisposantderelationsdhritage.
Commelesobjetsdesclassesdrivespeuventtreconsidrscommedesinstancesdeleursclasses
debase, lesgestionnairesdexceptionpeuvent rcuprerlesexceptionsdecesclassesdrivesen
rcuprant unobjet dutypedunedeleursclassesdebase.
Ainsi, il est possibledeclassifierles
diffrentscasderreursendfinissantunehirarchiedeclassedexceptions,etdcriredestraitements
gnriquesennutilisantquelesobjetsduncertainniveaudanscettehirarchie.
Lemcanismedesexceptionssemontredoncpluspuissantquetouteslesautresmthodesdetraite
mentderreursceniveau,puisquelaslectiondugestionnairederreurestautomatiquementralise
parlelangage.Celapeuttretrspratiquepourpeuquelonaitdfinicorrectementsahirarchiede
classesdexceptions.
Exemple94.Classificationdesexceptions
#include <iostream>
usingnamespacestd;
//Classedebasedetouteslesexceptions:
classExRuntimeError
{
};
//Classedebasedesexceptionspouvantseproduire
//lorsdemanipulationsdefichiers:
classExFileError:publicExRuntimeError
{
};
//Classesdeserreursdemanipulationdesfichiers:
classExInvalidName:publicExFileError
{
};
classExEndOfFile:publicExFileError
{
};
classExNoSpace:publicExFileError
{
};
classExMediumFull:publicExNoSpace
{
};
classExFileSizeMaxLimit:publicExNoSpace
{

156

Chapitre9.LesexceptionsenC++
};
//Fonctionfaisantuntravailquelconquesurunfichier:
voidWriteData(constchar*szFileName)
{
//Exemplederreur:
if(szFileName==NULL)throwExInvalidName();
else
{
//Traitementdelafonction
//etc.
//Lancementduneexception:
throwExMediumFull();
}
}
voidSave(constchar*szFileName)
{
try
{
WriteData(szFileName);
}
//Traitementdunerreurspcifique:
catch(ExInvalidName&)
{
cout << "Impossibledefairelasauvegarde" << endl;
}
//Traitementdetouteslesautreserreursengroupe:
catch(ExFileError&)
{
cout << "Erreurdentre/sortie"<< endl;
}
}
intmain(void)
{
Save(NULL);
Save("data.dat");
return0;
}

LabibliothquestandardC++dfinitellemmeuncertainnombredexceptionsstandards,quisont
utilisespoursignalerleserreursquiseproduisentlexcutiondesprogrammes.Quelquesunesde
cesexceptionsontdjtprsentesaveclesfonctionnalitsquisontsusceptiblesdeleslancer.Vous
trouverezunelistecompltedesexceptionsdelabibliothquestandardduC++danslaSection13.2.

9.5.Exceptionsdanslesconstructeurs
Ilestparfaitementlgaldelanceruneexceptiondansunconstructeur.Enfait,cestmmelaseule
solutionpoursignaleruneerreurlorsdelaconstructiondunobjet,puisquelesconstructeursnont
pasdevaleurderetour.
Lorsquuneexceptionest lancepartirdunconstructeur, laconstructiondelobjet choue. Par
consquent,lecompilateurnappellerajamaisledestructeurpourcetobjet,puisquecelanapasde

157

Chapitre9.LesexceptionsenC++
sens.Cependant,cecomportementsoulveleproblmedesobjetspartiellementinitialiss,pourles
quelsilestncessairedefaireunpeudenettoyagelasuitedulancementdelexception.LeC++
disposedoncdunesyntaxeparticulirepourlesconstructeursdesobjetssusceptiblesdelancerdes
exceptions. Cettesyntaxepermetsimplementdutiliserunbloc try pourlecorpsdefonctiondes
constructeurs.Lesblocs catch suiventalorsladfinitionduconstructeur,eteffectuentlalibration
desressourcesqueleconstructeurauraitpualloueravantquelexceptionneseproduise.
Lecomportementdubloc catch desconstructeursavecbloc try estdiffrentdeceluidesblocs
catch classiques.Eneffet,lesexceptionsnesontnormalementpasrelancesunefoisquellesont
ttraites.Commeonlavucidessus,ilfaututiliserexplicitementlemotcl throw pourrelancer
uneexceptionlissuedesontraitement.Danslecasdesconstructeursavecunbloc try cependant,
lexceptionestsystmatiquementrelance.Lebloc catch duconstructeurnedoitdoncprendreen
chargequeladestructiondesdonnesmembrespartiellementconstruites, etilfauttoujourscapter
lexceptionauniveauduprogrammequiacherchcrerlobjet.
Note: Cettedernirergleimpliquequelesprogrammesdclarant desobjetsglobauxdont
leconstructeurpeut lanceruneexceptionrisquent deseterminerencatastrophe. Eneffet, si
uneexceptionestlanceparceconstructeurlinitialisationduprogramme,aucungestionnaire
dexceptionneseraenmesuredelacapterlorsquelebloccatch larelancera.

Demme, lorsquelaconstructiondelobjet sefait danslecadreduneallocationdynamiquede


mmoire,lecompilateurappelleautomatiquementloprateur delete afinderestituerlammoire
allouepourcetobjet.Ilestdoncinutilederestituerlammoiredelobjetalloudansletraitement
delexceptionquisuitlacrationdynamiquedelobjet,etilnefautpasyappelerloprateur delete
manuellement.
Note:Commeil latditplushaut,lecompilateurnappellepasledestructeurpourlesobjets
dontleconstructeuragnruneexception.Cettergleestvalidemmedanslecasdesobjets
allousdynamiquement.Lecomportementdeloprateur delete estdonclui aussi lgrement
modifiparlefaitquelexceptionsestproduitedansunconstructeur.

Exemple95.Exceptionsdanslesconstructeurs
#include <iostream>
#include <stdlib.h>
usingnamespacestd;
classA
{
char*pBuffer;
int *pData;
public:
A()throw(int);
~A()
{
cout << "A::~A()" << endl;
}
staticvoid*operatornew(size_ttaille)

158

Chapitre9.LesexceptionsenC++
{
cout << "new()" << endl;
returnmalloc(taille);
}
staticvoidoperatordelete(void*p)
{
cout << "delete" << endl;
free(p);
}
};
//Constructeursusceptibledelanceruneexception:
A::A()throw(int)
try
{
pBuffer=NULL;
pData=NULL;
cout << "Dbutduconstructeur" << endl;
pBuffer=newchar[256];
cout << "Lancementdelexception"<< endl;
throw2;
//Codeinaccessible:
pData=newint;
}
catch(int)
{
cout << "Jefaislemnage..."
<< endl;
delete[]pBuffer;
deletepData;
}

intmain(void)
{
try
{
A*a=newA;
}
catch(...)
{
cout << "Ae,mmepasmal!"
}
return0;
}

<< endl;

Danscetexemple,lorsdelacrationdynamiquedunobjetA,uneerreurdinitialisationseproduit
et uneexceptionest lance. Celleci est alorstraitedanslebloc catch qui suit ladfinitiondu
constructeurdelaclasseA.Loprateur delete estbienappelautomatiquement,maisledestructeur
deAnestjamaisexcut.
Engnral, siuneclassehritedeuneouplusieursclassesdebase, lappelauxconstructeursdes
classesdebasedoitsefaireentrelemotcl try etlapremireaccolade.Eneffet,lesconstructeurs
desclassesdebasesont susceptibles, euxaussi, delancerdesexceptions. Lasyntaxeest alorsla
suivante:
Classe::Classe

159

Chapitre9.LesexceptionsenC++
try:Base(paramtres)[,Base(paramtres)[...]]
{
}
catch...

160

Chapitre10.Identificationdynamiquedes
types
LeC++estunlangagefortementtyp.Malgrcela,ilsepeutqueletypeexactdunobjetsoitinconnu
causedelhritage.Parexemple,siunobjetestconsidrcommeunobjetduneclassedebasede
savritableclasse,onnepeutpasdtermineraprioriquelleestsavritablenature.
Cependant,lesobjetspolymorphiques(qui,rappelonsle,sontdesobjetsdisposantdemthodesvir
tuelles)conserventdesinformationssurleurtypedynamique,savoirleurvritablenature.Eneffet,
lorsdelappeldesmthodesvirtuelles,lamthodeappeleestlamthodedelavritableclassede
lobjet.
Ilestpossibledutilisercettepropritpourmettreenplaceunmcanismepermettantdidentifierle
typedynamiquedesobjets,maiscettemaniredeprocdernestpasportable.LeC++fournitdonc
unmcanismestandardpermettantdemanipulerlesinformationsdetypedesobjetspolymorphiques.
Cemcanismeprendenchargelidentificationdynamiquedestypesetlavrificationdelavalidit
destranstypagesdanslecadredeladrivation.

10.1.Identificationdynamiquedestypes
10.1.1.Loprateurtypeid
LeC++fournitloprateur typeid,quipermetdercuprerlesinformationsdetypedesexpressions.
Sasyntaxeestlasuivante:
typeid(expression)

o expression estlexpressiondontilfautdterminerletype.
Lersultatdeloprateur typeid estunerfrencesurunobjetconstantdeclassetype_info.Cette
classeseradcritedanslaSection10.1.2.
Lesinformationsdetypercupressontlesinformationsdetypestatiquepourlestypesnonpoly
morphiques.Celasignifiequelobjetrenvoypartypeid caractriseraletypedelexpressionfournie
enparamtre,quecetteexpressionsoitunsousobjetdunobjetplusdrivounon.Enrevanche,pour
lestypespolymorphiques,siletypenepeutpastredterminstatiquement(cestdirelacom
pilation),unedterminationdynamique(cestdirelexcution)dutypealieu,etlobjetdeclasse
type_inforenvoydcritlevraitypedelexpression(mmesiellereprsenteunsousobjetdunobjet
duneclassedrive).Cettesituationpeutarriverlorsquonmanipuleunobjetlaidedunpointeur
oudunerfrencesuruneclassedebasedelaclassedecetobjet.
Exemple101.Oprateurtypeid
#include <typeinfo>
usingnamespacestd;
classBase
{
public:
virtual~Base(void);

//Ilfautunefonctionvirtuelle
//pouravoirdupolymorphisme.

161

Chapitre10.Identificationdynamiquedestypes
};
Base::~Base(void)
{
return;
}
classDerivee:publicBase
{
public:
virtual~Derivee(void);
};
Derivee::~Derivee(void)
{
return;
}
intmain(void)
{
Derivee*pd=newDerivee;
Base*pb=pd;
consttype_info&t1=typeid(*pd); //t1qualifieletypede*pd.
consttype_info&t2=typeid(*pb); //t2qualifieletypede*pb.
return0;
}

Lesobjets t1 et t2 sontgaux,puisquilsqualifienttouslesdeuxlemmetype(savoir,laclasse
Derivee). t2 necontientpaslesinformationsdetypedelaclasseBase, parcequelevraitypede
lobjetpointpar pb estlaclasseDerivee.
Note:Notezquelaclassetype_infoestdfiniedanslespacedenommage std::,rservla
bibliothquestandardC++,danslenttetypeinfo .Parconsquent,sonnomdoittreprcd
duprfixe std::.Vouspouvezvouspasserdeceprfixeenimportantlesdfinitionsdelespace
denommagedelabibliothquestandardlaidedunedirective using.Voustrouverezdeplus
amplesrenseignementssurlesespacesdenommagedansleChapitre11.

Onferabienattentiondrfrencerlespointeurs,carsinon,onobtientlesinformationsdetypesur
cepointeur,passurlobjetpoint.Silepointeurdrfrencestlepointeurnul,loprateur typeid
lanceuneexceptiondont lobjet est uneinstancedelaclassebad_typeid. Cetteclasseest dfinie
commesuitdanslentte typeinfo :
classbad_typeid:publiclogic
{
public:
bad_typeid(constchar*what_arg):logic(what_arg)
{
return;
}
voidraise(void)
{
handle_raise();
throw*this;
}

162

Chapitre10.Identificationdynamiquedestypes
};

10.1.2.Laclassetype_info
Lesinformationsdetypesontenregistresdansdesobjetsdelaclassetype_infoprdfinieparle
langage.Cetteclasseestdclaredanslentte typeinfo delamaniresuivante:
classtype_info
{
public:
virtual~type_info();
booloperator==(consttype_info&rhs)const;
booloperator!=(consttype_info&rhs)const;
boolbefore(consttype_info&rhs)const;
constchar*name()const;
private:
type_info(consttype_info&rhs);
type_info&operator=(consttype_info&rhs);
};

Lesobjetsdelaclassetype_infonepeuventpastrecopis,puisqueloprateurdaffectationetle
constructeurdecopiesonttouslesdeuxdclarsprivate.Parconsquent,leseulmoyendegnrer
unobjetdelaclassetype_infoestdutiliserloprateur typeid.
Lesoprateursdecomparaisonpermettentdetesterlgalitetladiffrencededeuxobjetstype_info,
cequirevientexactementcomparerlestypesdesexpressions.
Lesobjetstype_infocontiennentdesinformationssurlestypessouslaformedechanesdecaractres.
Unedeceschanesreprsenteletypesousuneformelisibleparuntrehumain,etuneautresousune
formeplusappropriepourletraitementdestypes.Leformatdeceschanesdecaractresnestpas
prcisetpeutvarierduneimplmentationuneautre.Ilestpossibledercuprerlenomlisibledu
typelaidedelamthode name.Lavaleurrenvoyeestunpointeursurunechanedecaractres.On
nedoitpaslibrerlammoireutilisepourstockercettechanedecaractres.
Lamthode before permetdedterminerunordredanslesdiffrentstypesappartenantlamme
hirarchiedeclasses, ensebasant surlespropritsdhritage. Lutilisationdecettemthodeest
toutefoisdifficile, puisquelordreentrelesdiffrentesclassesnest
pasfixet peut dpendrede
limplmentation.

10.2.TranstypagesC++
Lesrglesdedrivationpermettentdassurerlefaitquelorsquonutiliseunpointeursuruneclasse,
lobjetpointexistebienetestbiendelaclassesurlaquellelepointeurestbas.Enparticulier,ilest
possibledeconvertirunpointeursurunobjetenunpointeursurunsousobjet.
Enrevanche,ilestinterditdutiliserunpointeursuruneclassedebasepourinitialiserunpointeursur
uneclassedrive.Pourtant,cetteoprationpeuttrelgale,sileprogrammeursaitquelepointeur
pointebiensurunobjetdelaclassedrive. Lelangageexigecependantuntranstypageexplicite.
Unetellesituationdemandelanalyseduprogrammeafindesavoirsielleestlgaleounon.

163

Chapitre10.Identificationdynamiquedestypes
Parfois,ilestimpossibledefairecetteanalyse.Celasignifiequeleprogrammeurnepeutpascertifier
quelepointeurdontildisposeestunpointeursurunsousobjet.Lemcanismedidentificationdyna
miquedestypespeuttrealorsutilispourvrifier,lexcution,siletranstypageestlgal.Silne
lestpas,untraitementparticulierdoittreeffectu,maissillest,leprogrammepeutsepoursuivre
normalement.
LeC++fournit unjeudoprateursdetranstypagequi permettent defairecesvrificationsdyna
miques,etquidoncsontnettementplussrsqueletranstypagetoutpuissantduCquelonautilis
jusquici.Cesoprateurssontcapablesdefaireuntranstypagedynamique,untranstypagestatique,
untranstypagedeconstanceetuntranstypagederinterprtationdesdonnes.Nousallonsvoirles
diffrentsoprateurspermettantdefairecestranstypages,ainsiqueleursignification.

10.2.1.Transtypagedynamique
Letranstypagedynamiquepermetdeconvertiruneexpressionenunpointeurouunerfrencedune
dynamic_cast.Cetoprateur
classe,ouunpointeursurvoid.Ilestralislaidedeloprateur
imposedesrestrictionslorsdestranstypagesafindegarantiruneplusgrandefiabilit:

ileffectueunevrificationdelavaliditdutranstypage;

ilnestpaspossibledliminerlesqualificationsdeconstance(pourcela,ilfaututiliserloprateur
const_cast,quelonverraplusloin).

Enrevanche,loprateurdynamic_cast permetparfaitementdaccrotrelaconstanceduntypecom
plexe,commelefontlesconversionsimplicitesdulangagevuesdanslaSection3.2etdanslaSection
4.7.
Ilnepeutpastravaillersurlestypesdebasedulangage,saufvoid*.
Lasyntaxedeloprateur dynamic_cast estdonnecidessous:
dynamic_cast<type>(expression)

o type dsigneletypecibledutranstypage,et

expression lexpressiontranstyper.

Letranstypagedunpointeuroudunerfrenceduneclassedriveenclassedebasesefaitdonc
directement, sansvrificationdynamique, puisquecetteoprationest toujoursvalide. Leslignes
suivantes:
//LaclasseBhritedelaclasseA:
B*pb;
A*pA=dynamic_cast <A* >(pB);

sontdoncstrictementquivalentescellesci:
//LaclasseBhritedelaclasseA:
B*pb;
A*pA=pB;

Toutautretranstypagedoitsefairepartirduntypepolymorphique,afinquelecompilateurpuisse
utiliserlidentificationdynamiquedestypeslorsdutranstypage.Letranstypagedunpointeurdun
objetversunpointeurdetypevoidrenvoieladressedudbutdelobjetleplusdriv,cestdire

164

Chapitre10.Identificationdynamiquedestypes
ladressedelobjetcomplet.Letranstypagedunpointeuroudunerfrencesurunsousobjetdun
objet versunpointeurouunerfrencedelobjet complet est effectuaprsvrificationdutype
dynamique. Silobjetpointourfrencestbiendutypeindiqupourletranstypage, lopration
sedroulecorrectement.Enrevanche,silnestpasdubontype, dynamic_cast neffectuepasle
transtypage.Siletypecibleestunpointeur,lepointeurnulestrenvoy.Sienrevanchelexpression
caractriseunobjetouunerfrencedobjet,uneexceptiondetypebad_castestlance.
Laclassebad_castestdfiniecommesuitdanslentte typeinfo :
classbad_cast:publicexception
{
public:
bad_cast(void)throw();
bad_cast(constbad_cast&)throw();
bad_cast&operator=(constbad_cast&)throw();
virtual~bad_cast(void)throw();
virtualconstchar*what(void)constthrow();
};

Lorsduntranstypage,aucuneambigutnedoitavoirlieupendantlarecherchedynamiquedutype.
Detellesambigutspeuventapparatredanslescasdhritagemultiple,oplusieursobjetsdemme
typepeuventcoexisterdanslemmeobjet.Cetterestrictionmisepart,loprateur dynamic_cast
estcapabledeparcourirunehirarchiedeclasseaussibienverticalement(convertirunpointeurde
sousobjetversunpointeurdobjetcomplet)quetransversalement(convertirunpointeurdobjetvers
unpointeurdunautreobjetfrredanslahirarchiedeclasses).
Loprateur dynamic_cast peuttreutilisdanslebutdeconvertirunpointeursuruneclassede
basevirtuelleversunedessesclassesfilles,cequenepouvaientpasfairelestranstypagesclassiques
duC. Enrevanche, ilnepeutpastreutilisafindaccderdesclassesdebasequinesontpas
visibles(enparticulier,lesclassesdebasehritesen private).
Exemple102.Oprateurdynamic_cast
structA
{
virtualvoidf(void)
{
return;
}
};
structB:virtualpublicA
{
};
structC:virtualpublicA,publicB
{
};
structD
{
virtualvoidg(void)
{
return;
}

165

Chapitre10.Identificationdynamiquedestypes
};
structE:publicB,publicC,publicD
{
};
intmain(void)
{
Ee;

//econtientdeuxsousobjetsdeclasseB
//(maisunseulsousobjetdeclasseA).
//LessousobjetsdeclasseCetDsont
//frres.
A*pA=&e;
//Drivationlgale:lesousobjet
//declasseAestunique.
//C*pC=(C*)pA;//Illgal:Aestuneclassedebase
//virtuelle(erreurdecompilation).
C*pC=dynamic_cast <C* >(pA); //Lgal.Transtypage
//dynamiquevertical.
D*pD=dynamic_cast <D* >(pC); //Lgal.Transtypage
//dynamiquehorizontal.
B*pB=dynamic_cast <B* >(pA); //Lgal,maischouera
//lexcution(ambigut).
return0;

10.2.2.Transtypagestatique
Contrairementautranstypagedynamique,letranstypagestatiqueneffectueaucunevrificationdes
typesdynamiqueslorsdutranstypage.Ilestdoncnettementplusdangereuxqueletranstypagedyna
mique.Cependant,contrairementautranstypageCclassique,ilnepermettoujourspasdesupprimer
lesqualificationsdeconstance.
Letranstypagestatiqueseffectuelaidedeloprateur static_cast,dontlasyntaxeestexacte
mentlammequecelledeloprateur dynamic_cast :
static_cast<type>(expression)

o type et expression ontlammesignificationquepourloprateur

dynamic_cast.

Essentiellement,loprateur static_cast neffectueloprationdetranstypagequesilexpression


suivanteestvalide:
typetemporaire(expression);

Cetteexpressionconstruitunobjettemporairequelconquedetypetypeetlinitialiseaveclavaleur
deexpression.Contrairementloprateur dynamic_cast,loprateur static_cast permetdonc
deffectuerlesconversionsentrelestypesautresquelesclassesdfiniesparlutilisateur.
Aucune
vrificationdelavaliditdelaconversionnalieucependant(commepourletranstypageCclassique).
Si unetelleexpressionnest pasvalide, letranstypagepeut malgrtout avoirlieusil sagit dun
transtypageentreclassesdrivesetclassesdebase.Loprateur static_cast permetdeffectuer
lestranstypagesdecetypedanslesdeuxsens(classedebaseversclassedriveetclassedrive
versclassedebase). Letranstypageduneclassedebaseversuneclassedrivenedoit
trefait

166

Chapitre10.Identificationdynamiquedestypes
quelorsquonestsrquilnyapasdedanger,puisquaucunevrificationdynamiquenalieuavec
static_cast.
Enfin,touteslesexpressionspeuventtreconvertiesenvoidavecdesqualificationsdeconstanceet
devolatilit.Cetteoprationasimplementpourbutdesupprimerlavaleurdelexpression(puisque
voidreprsenteletypevide).

10.2.3.Transtypagedeconstanceetdevolatilit
Lasuppressiondesattributsdeconstanceet
devolatilitpeut treralisegrceloprateur
const_cast.Cetoprateursuitexactementlammesyntaxequelesoprateurs dynamic_cast et
static_cast :
const_cast<type>(expression)

Loprateur const_cast peuttravailleressentiellementavecdesrfrencesetdespointeurs.Ilper


metderaliserlestranstypagesdontletypedestinationestmoinscontraintqueletypesourcevisvis
desmotscls const et volatile.
Enrevanche, loprateur const_cast nepermet pas deffectuer dautres conversions queles
autresoprateursdetranstypage(ousimplement
lestranstypagesCclassiques) peuvent raliser.
Parexemple, il est impossibledelutiliserpourconvertirunflottant enentier. Lorsquil travaille
avecdesrfrences, loprateur const_cast vrifiequeletranstypageest lgal enconvertissant
const et
lesrfrencesenpointeursetenregardantsiletranstypagenimpliquequelesattributs
volatile. const_cast nepermetpasdeconvertirlespointeursdefonctions.

10.2.4.Rinterprtationdesdonnes
Loprateurdetranstypageleplusdangereuxest reinterpret_cast.Sasyntaxeestlammeque
celledesautresoprateursdetranstypage dynamic_cast, static_cast et const_cast :
reinterpret_cast<type>(expression)

Cetoprateurpermetderinterprterlesdonnesduntypeenunautretype.Aucunevrificationde
lavaliditdecetteoprationnestfaite.Ainsi,leslignessuivantes:
doublef=2.3;
inti=1;
const_cast<int& >(f)=i;

sontstrictementquivalentesauxlignessuivantes:
doublef=2.3;
inti=1;
*((int*)&f)=i;

Loprateur reinterpret_cast doitcependantrespecterlesrglessuivantes:

ilnedoitpaspermettrelasuppressiondesattributsdeconstanceetdevolatilit;

167

Chapitre10.Identificationdynamiquedestypes

168

ildoittresymtrique(cestdirequelarinterprtationduntypeT1entantquetypeT2,puisla
rinterprtationdursultatentypeT1doitredonnerlobjetinitial).

Chapitre11.Lesespacesdenommage
Lesespacesdenommagesontdeszonesdedclarationquipermettentdedlimiterlarecherchedes
nomsdesidentificateursparlecompilateur. Leurbutestessentiellementderegrouperlesidentifi
cateurslogiquementetdviterlesconflitsdenomsentreplusieurspartiesdunmmeprojet.
Par
exemple,sideuxprogrammeursdfinissentdiffremmentunemmestructuredansdeuxfichiersdif
frents,unconflitentrecesdeuxstructuresauralieuaumieuxlditiondeliens,etaupirelorsde
lutilisationcommunedessourcesdecesdeuxprogrammeurs.Cetypedeconflitprovientdufaitque
leC++nefournitquunseulespacedenommagedeporteglobale,
danslequelilnedoityavoir
aucunconflitdenom.Grceauxespacesdenommagenonglobaux,cetypedeproblmepeuttre
plusfacilementvit,parcequelonpeutviterdedfinirlesobjetsglobauxdanslaporteglobale.

11.1.Dfinitiondesespacesdenommage
11.1.1.Espacesdenommagenommes
Lorsqueleprogrammeurdonneunnomunespacedenommage,celuiciestappelunespacede
nommagenomm.Lasyntaxedecetypedespacedenommageestlasuivante:
namespacenom
{
dclarations|dfinitions
}
nom estlenomdelespacedenommage,et dclarations et dfinitions sontlesdclarationset

lesdfinitionsdesidentificateursquiluiappartiennent.
Contrairementauxrgionsdclarativesclassiquesdulangage(commeparexemplelesclasses),un
namespace peuttredcoupenplusieursmorceaux.Lepremiermorceauxsertdedclaration,etles
suivantsdextensions.Lasyntaxepouruneextensiondespacedenommageestexactementlamme
quecelledelapartiededclaration.
Exemple111.Extensiondenamespace
namespaceA
{
inti;
}

//DclarationdelespacedenommageA.

namespaceB
{
inti;
}

//DclarationdelespacedenommageB.

namespaceA
{
intj;
}

//ExtensiondelespacedenommageA.

Lesidentificateursdclarsoudfinislintrieurdunmmeespacedenommagenedoiventpas
entrerenconflit.Ilspeuventavoirlesmmesnoms,maisseulementdanslecadredelasurcharge.Un

169

Chapitre11.Lesespacesdenommage
espacedenommagesecomportedoncexactementcommeleszonesdedclarationdesclassesetde
laporteglobale.
Laccsauxidentificateursdesespacesdenommagesefaitpardfautgrceloprateurdersolution
deporte( ::),etenqualifiantlenomdelidentificateurutiliserdunomdesonespacedenommage.
Cependant,cettequalificationestinutilelintrieurdelespacedenommageluimme,exactement
commepourlesmembresdesclasseslintrieurdeleurclasse.
Exemple112.Accsauxmembresdunnamespace
inti=1;

//iestglobal.

namespaceA
{
inti=2;//idelespacedenommageA.
intj=i;//UtiliseA::i.
}
intmain(void)
{
i=1;
//Utilise::i.
A::i=3; //UtiliseA::i.
return0;
}

Lesfonctionsmembresdunespacedenommagepeuventtredfinieslintrieurdecetespace,
exactementcommelesfonctionsmembresdeclasses.Ellespeuventgalementtredfiniesendehors
decetespace,silonutiliseloprateurdersolutiondeporte.Lesfonctionsainsidfiniesdoivent
apparatreaprsleurdclarationdanslespacedenommage.
Exemple113.Dfinitionexternedunefonctiondenamespace
namespaceA
{
intf(void);
}
intA::f(void)
{
return0;
}

//DclarationdeA::f.

//DfinitiondeA::f.

Ilestpossiblededfinirunespacedenommagelintrieurdunautreespacedenommage.Cepen
dant,cettedclarationdoitobligatoirementavoirlieuauniveaudclaratifleplusexternedelespace
denommagequicontientlesousespacedenommage. Onnepeutdoncpasdclarerdespacesde
nommagelintrieurdunefonctionoulintrieurduneclasse.
Exemple114.Dfinitiondenamespacedansunnamespace
namespaceConteneur
{
inti;
namespaceContenu
{
intj;
}

170

//Conteneur::i.

//Conteneur::Contenu::j.

Chapitre11.Lesespacesdenommage
}

11.1.2.Espacesdenommageanonymes
Lorsque,lorsdeladclarationdunespacedenommage,aucunnomnestdonn,unespacedenom
mageanonymeestcr.Cetypedespacedenommagepermetdassurerlunicitdunomdelespace
denommageainsidclar.Lesespacesdenommageanonymespeuventdoncremplacerefficacement
lemotcl static pourrendreuniquedesidentificateursdansunfichier.Cependant,ellessontplus
puissantes,parcequelonpeutgalementdclarerdesespacesdenommageanonymeslintrieur
dautresespacesdenommage.
Exemple115.Dfinitiondenamespaceanonyme
namespace
{
inti;
}

//quivalentunique::i;

Danslexempleprcdent, ladclarationde i sefaitdansunespacedenommagedontlenomest


choisiparlecompilateurdemanireunique.Cependant,commeonneconnatpascenom,lecom
pilateurutiliseunedirective using (voirplusloin)afindepouvoirutiliserlesidentificateursdecet
espacedenommageanonymesansprciserleurnomcompletavecloprateurdersolutiondeporte.
Si,dansunespacedenommage,unidentificateurestdclaraveclemmenomquunautreidenti
ficateurdclardansunespacedenommageplusglobal,lidentificateurglobalestmasqu.Deplus,
lidentificateurainsidfininepeuttreaccdendehorsdesonespacedenommagequeparunnom
compltementqualifilaidedeloprateurdersolutiondeporte.Toutefois,silespacedenom
magedanslequelilestdfiniestunespacedenommageanonyme,cetidentificateurnepourrapas
trerfrenc,puisquonnepeutpasprciserlenomdesespacesdenommageanonymes.
Exemple116.Ambigutsentrenamespaces
namespace
{
inti;
}
voidf(void)
{
++i;
}
namespaceA
{
namespace
{
inti;
intj;
}
voidg(void)
{
++i;

//Dclareunique::i.

//Utiliseunique::i.

//DfinitA::unique::i.
//DfinitA::unique::j.

//Erreur:ambigutentreunique::i
//etA::unique::i.

171

Chapitre11.Lesespacesdenommage
++A::i;
++j;

//Erreur:A::inestpasdfini
//(seulA::unique::ilest).
//Correct:++A::unique::j.

}
}

11.1.3.Aliasdespacesdenommage
Lorsquunespacedenommageporteunnomtrscompliqu,
aliaspourcenom.Laliasauraalorsunnomplussimple.

ilpeuttreavantageuxdedfinirun

Cetteoprationpeuttreraliselaidedelasyntaxesuivante:
namespacenom_alias=nom;
nom_alias est ici lenomdelaliasdelespacedenommage,

et nom est lenomdelespacede

nommageluimme.
Lesnomsdonnsauxaliasdespacesdenommagenedoiventpasentrerenconflitaveclesnomsdes
autresidentificateursdummeespacedenommage,queceluicisoitlespacedenommagedeporte
globaleounon.

11.2.Dclarationusing
Lesdclarationsusingpermettentdutiliserunidentificateurdunespacedenommagedemanire
simplifie,sansavoirspcifiersonnomcomplet(cestdirelenomdelespacedenommagesuivi
dunomdelidentificateur).

11.2.1.Syntaxedesdclarationsusing
Lasyntaxedesdclarationsusingestlasuivante:
usingidentificateur;

o identificateur estlenomcompletdelidentificateurutiliser,avecqualificationdespacede
nommage.
Exemple117.Dclarationusing
namespaceA
{
inti;
intj;
}
voidf(void)
{
usingA::i;
i=1;
j=1;
return;

172

//DclareA::i.
//DclareA::j.

//A::ipeuttreutilissouslenomi.
//quivalentA::i=1.
//Erreur!jnestpasdfini!

Chapitre11.Lesespacesdenommage
}

Lesdclarations using permettentenfaitdedclarerdesaliasdesidentificateurs.Cesaliasdoivent


treconsidrsexactement commedesdclarationsnormales. Celasignifiequilsnepeuvent tre
dclarsplusieursfoisquelorsquelesdclarationsmultiplessontautorises(dclarationsdevariables
oudefonctionsendehorsdesclasses),etdeplusilsappartiennentlespacedenommagedanslequel
ilssontdfinis.
Exemple118.Dclarationsusingmultiples
namespaceA
{
inti;
voidf(void)
{
}
}
namespaceB
{
usingA::i;
usingA::i;
usingA::f;

//DclarationdelaliasB::i,quireprsenteA::i.
//Lgal:doubledclarationdeA::i.
//DclarevoidB::f(void),
//fonctionidentiqueA::f.

}
intmain(void)
{
B::f();
return0;
}

//AppelleA::f.

Laliascrparunedclaration using permetderfrenceruniquementlesidentificateursquisont


visiblesaumomentoladclaration using estfaite.Silespacedenommageconcernparladcla
ration using esttenduaprscettedernire,lesnouveauxidentificateursdemmenomqueceluide
laliasneserontpasprisencompte.
Exemple119.Extensiondenamespaceaprsunedclarationusing
namespaceA
{
voidf(int);
}
usingA::f;
namespaceA
{
voidf(char);

//festsynonymedeA::f(int).

//festtoujourssynonymedeA::f(int),
//maispasdeA::f(char).

}
voidg()
{
f(a);

//AppelleA::f(int),mmesiA::f(char)

173

Chapitre11.Lesespacesdenommage
//existe.
}

Siplusieursdclarationslocaleset using dclarentdesidentificateursdemmenom,


oubiences
identificateursdoiventtousserapporteraummeobjet,oubienilsdoiventreprsenterdesfonctions
ayantdessignaturesdiffrentes(lesfonctionsdclaressontdoncsurcharges).Danslecascontraire,
desambigutspeuventapparatreetlecompilateursignaleuneerreurlorsdeladclarationusing.
Exemple1110.Conflitentredclarationsusingetidentificateurslocaux
namespaceA
{
inti;
voidf(int);
}
voidg(void)
{
inti;
//Dclarationlocaledei.
usingA::i;
//Erreur:iestdjdclar.
voidf(char);//Dclarationlocaledef(char).
usingA::f;
//Pasderreur,ilyasurchargedef.
return;
}
Note:Cecomportement diffredecelui desdirectives using. Eneffet, lesdirectives using
reportentladtectiondeserreurslapremireutilisationdesidentificateursambigus.

11.2.2.Utilisationdesdclarationsusingdanslesclasses
Unedclaration using peut treutilisedansladfinitionduneclasse. Danscecas, elledoit se
rapporteruneclassedebasedelaclassedanslaquelleelleestutilise.Deplus,lidentificateurdonn
ladclaration using doittreaccessibledanslaclassedebase(cestdiredetype protected ou
public).
Exemple1111.Dclarationusingdansuneclasse
namespaceA
{
floatf;
}
classBase
{
inti;
public:
intj;
};
classDerivee:publicBase
{
usingA::f;
//Illgal:fnestpasdansuneclasse

174

Chapitre11.Lesespacesdenommage

usingBase::i;
public:
usingBase::j;
};

//debase.
//Interdit:Deriveenapasledroit
//dutiliserBase::i.
//Lgal.

Danslexempleprcdent, seulelatroisimedclarationestvalide, parcequecestlaseulequise


rfreunmembreaccessibledelaclassedebase.Lemembre j dclarseradoncunsynonymede
Base::j danslaclasseDerivee.
Engnral, lesmembresdesclassesdebasesontaccessiblesdirectement. Quelleestdonclutilit
desdclarations using danslesclasses?Enfait,ellespeuventtreutilisespourrtablirlesdroits
daccs,modifisparunhritage,desmembresdeclassesdebase.Pourcela,ilsuffitdeplacerla
dclaration using dansunezonededclarationdummetypequecelledanslaquellelemembrese
trouvaitdanslaclassedebase.Cependant,commeonlavucidessus,uneclassenepeutpasrtablir
lesdroitsdaccsdunmembredeclassedebasedclarenzone private.
Exemple1112.Rtablissementdedroitsdaccslaidedunedirectiveusing
classBase
{
public:
inti;
intj;
};
classDerivee:privateBase
{
public:
usingBase::i; //RtablitlaccessibilitsurBase::i.
protected:
usingBase::i; //Interdit:restreintlaccessibilit
//surBase::iautrementqueparhritage.
};
Note:Certainscompilateursinterprtentdiffremmentleparagraphe11.3delanormeC++,qui
concernelaccessibilitdesmembresintroduitsavecunedclarationusing.Seloneux,lesdc
larations using permettentderestreindrelaccessibilitdesdroitsetnonpasdelesrtablir.Cela
impliquequil estimpossiblederedonnerlaccessibilitdesdonnespourlesquelleslhritage
arestreintlaccs.Parconsquent,lhritagedoittrefaitdelamanirelapluspermissivepos
sible,etlesaccsdoiventtreajustsaucasparcas.Bienquecetteinterprtationsoittoutfait
valable,lexempledonndanslanormeC++sembleindiquerquellenestpascorrecte.

Quandunefonctionduneclassedebaseestintroduitedansuneclassedrivelaidedunedclara
tion using,etquunefonctiondemmenometdemmesignatureestdfiniedanslaclassedrive,
cettedernirefonctionsurchargelafonctiondelaclassedebase.Ilnyapasdambigutdanscecas.

175

Chapitre11.Lesespacesdenommage

11.3.Directiveusing
Ladirectiveusingpermetdutiliser,sansspcificationdespacedenommage,nonpasunidentificateur
commedanslecasdeladclaration using,maistouslesidentificateursdecetespacedenommage.
Lasyntaxedeladirectiveusingestlasuivante:
usingnamespacenom;

o nom estlenomdelespacedenommagedontlesidentificateursdoiventtreutilisssansqualifi
cationcomplte.
Exemple1113.Directiveusing
namespaceA
{
inti;
intj;
}

//DclareA::i.
//DclareA::j.

voidf(void)
{
usingnamespaceA;//OnutiliselesidentificateursdeA.
i=1;
//quivalentA::i=1.
j=1;
//quivalentA::j=1.
return;
}

Aprsunedirective using,ilesttoujourspossibledutiliserlesnomscompletsdesidentificateursde
lespacedenommage,maiscenestplusncessaire.Lesdirectives using sontvalidespartirdela
ligneoellessontdclaresjusqulafindublocdeportecourante.Siunespacedenommageest
tenduaprsunedirective using,lesidentificateursdfinisdanslextensiondelespacedenommage
peuventtreutilissexactementcommelesidentificateursdfinisavantladirective using (cest
diresansqualificationcompltedeleursnoms).
Exemple1114.Extensiondenamespaceaprsunedirectiveusing
namespaceA
{
inti;
}
usingnamespaceA;
namespaceA
{
intj;
}
voidf(void)
{
i=0;
//InitialiseA::i.
j=0;
//InitialiseA::j.
return;
}

176

Chapitre11.Lesespacesdenommage
Ilsepeutquelorsdelintroductiondesidentificateursdunespacedenommageparunedirective
using,desconflitsdenomsapparaissent.Danscecas,aucuneerreurnestsignalelorsdeladirective
using. Enrevanche, uneerreurseproduitsiundesidentificateurspourlesquelsilyaconflitest
utilis.
Exemple1115.Conflitentredirectiveusingetidentificateurslocaux
namespaceA
{
inti;
}

//DfinitA::i.

namespaceB
{
inti; //DfinitB::i.
usingnamespaceA;
//A::ietB::isontenconflit.
//Cependant,aucuneerreurnapparat.
}
voidf(void)
{
usingnamespaceB;
i=2;
//Erreur:ilyaambigut.
return;
}

177

Chapitre11.Lesespacesdenommage

178

Chapitre12.Lestemplate
12.1.Gnralits
Nousavonsvuprcdemmentcommentraliserdesstructuresdedonnesrelativementindpendantes
delaclassedeleursdonnes(cestdiredeleurtype)aveclesclassesabstraites.Parailleurs,ilest
faisabledefairedesfonctionstravaillantsurdenombreuxtypesgrcelasurcharge.Jerappellequen
C++,touslestypessontenfaitdesclasses.
Cependant, lemploi desclassesabstraitesest assezfastidieuxet alinconvnient daffaiblir le
contrledestypesralisparlecompilateur.Deplus,lasurchargenestpasgnralisablepourtous
lestypesdedonnes.Ilseraitpossibledutiliserdesmacrospourfairedesfonctionsatypiquesmais
celaseraitaudtrimentdelatailleducode.
LeC++permet dersoudrecesproblmesgrceauxparamtresgnriques, quelonappelleen
coreparamtrestemplate. Unparamtre template estsoituntypegnrique, soituneconstante
template
dontletypeestassimilableuntypeintgral.Commeleurnomlindique,lesparamtres
permettentdeparamtrerladfinitiondesfonctionsetdesclasses.Lesfonctionsetlesclassesainsi
paramtressontappelesrespectivementfonctionstemplateetclassestemplate.
Lesfonctionstemplatesontdoncdesfonctionsquipeuventtravaillersurdesobjetsdontletypeestun
typegnrique(cestdireuntypequelconque),ouquipeuventtresparamtrsparuneconstante
detypeintgral.Lesclassestemplatesontdesclassesquicontiennentdesmembresdontletypeest
gnriqueouquidpendentdunparamtreintgral.
Engnral, lagnrationducodealieulorsduneoprationaucoursdelaquellelestypesgn
riquessontremplacspardesvraistypesetlesparamtresdetypeintgralprennentleurvaleur.Cette
oprationsappellelinstanciationdestemplate.Ellealieulorsquonutiliselafonctionoulaclasse
template pourlapremirefois.Lestypesrelsutiliserlaplacedestypesgnriquessontd
terminslorsdecettepremireutilisationparlecompilateur,soitimplicitementpartirducontexte
dutilisationdu template,soitparlesparamtresdonnsexplicitementparleprogrammeur.

12.2.Dclarationdesparamtrestemplate
Lesparamtres template sont,commeonlavu,soitdestypesgnriques,soitdesconstantesdont
letypepeuttreassimiluntypeintgral.

12.2.1.Dclarationdestypestemplate
Les template quisontdestypesgnriquessontdclarsparlasyntaxesuivante:
template <class|typenamenom[=type]
[,class|typenamenom[=type]
[...]>

o nom estlenomquelondonneautypegnriquedanscettedclaration.Lemotcl class aici


exactementlasignificationdetype. Ilpeutdailleurstreremplacindiffremmentdanscette
syntaxeparlemotcl typename.Lammedclarationpeuttreutilisepourdclarerunnombre
arbitrairedetypesgnriques,enlessparantpardesvirgules.Lesparamtres template quisont
destypespeuventprendredesvaleurspardfaut,enfaisantsuivrelenomduparamtredunsigne
galetdelavaleur.Ici,lavaleurpardfautdoitvidemmenttreuntypedjdclar.

179

Chapitre12.Lestemplate
Exemple121.Dclarationdeparamtrestemplate
template <classT,typenameU,classV=int
>

Danscetexemple,T,UetVsontdestypesgnriques.Ilspeuventremplacernimportequeltypedu
langagedjdclaraumomentoladclaration template estfaite.Deplus,letypegnriqueVa
pourvaleurpardfautletypeentierint.Onvoitbiendanscetexemplequelesmotscls typename
et class peuventtreutilissindiffremment.
Lorsquondonnedesvaleurspardfautuntypegnrique,ondoitdonnerdesvaleurspardfaut
touslestypesgnriquesquilesuiventdansladclaration template.Lalignesuivanteprovoquera
doncuneerreurdecompilation:
template <classT=int,classV >

Ilestpossibledutiliseruneclasse template entantquetypegnrique.Danscecas,laclassedoit


tredclarecommetant template lintrieurmmedeladclaration template.Lasyntaxeest
donclasuivante:
template <template <classType> classClasse[,...]>

oTypeestletypegnriqueutilisdansladclarationdelaclasse template Classe.Onappelle


lesparamtres template qui sont desclasses template desparamtrestemplatetemplate. Rien
ninterditdedonnerunevaleurpardfautunparamtre templatetemplate :letypeutilisdoit
alorstreuneclasse template dclareavantladclaration template.
Exemple122.Dclarationdeparamtretemplatetemplate
template <classT >
classTableau
{
//Dfinitiondelaclasse template Tableau.
};
template <classU,classV,template<classT > classC=Tableau>
classDictionnaire
{
C<U> Clef;
C<V> Valeur;
//RestedeladfinitiondelaclasseDictionnaire.
};

Danscetexemple,laclassetemplate Dictionnairepermetderelierdesclsleurslments.Cescls
etcesvaleurspeuventprendrenimportequeltype.Lesclsetlesvaleurssontstockesparalllement
danslesmembres Clef et Valeur .Cesmembressontenfaitdesconteneurs template,dontla
classeestgnriqueetdsigneparleparamtre templatetemplate C.Leparamtre template
deCestutilispourdonnerletypedesdonnesstockes,savoirlestypesgnriquesUetVdans
lecasdelaclasseDictionnaire.Enfin,laclasseDictionnairepeututiliserunconteneurpardfaut,qui
estlaclasse template Tableau.
Pourplusdedtailssurladclarationdesclasses template,voirlaSection12.3.2.

180

Chapitre12.Lestemplate

12.2.2.Dclarationdesconstantestemplate
Ladclarationdesparamtres template detypeconstantesefaitdelamaniresuivante:
template <typeparamtre[=valeur][,...]
>

o type estletypeduparamtreconstant, paramtre estlenomduparamtreet valeur estsa


valeurpardfaut.Ilestpossiblededonnerdesparamtres template quisontdestypesgnriques
etdesparamtres template quisontdesconstantesdanslammedclaration.
Letypedesconstantes template doitobligatoirementtrelundestypessuivants:

typeintgral(char,wchar_t,int,long,shortetleursversionssignesetnonsignes)ounumr;

pointeurourfrencedobjet;

pointeurourfrencedefonction;

pointeursurmembre.

Cesontdonctouslestypesquipeuventtreassimilsdesvaleursentires(entiers,
adresses).

numrsou

Exemple123.Dclarationdeparamtrestemplatedetypeconstante
template <classT,inti,void(*f)(int)
>

Cettedclaration template comprenduntypegnriqueT,uneconstante templatei detypeint,


et uneconstante templatef detypepointeursurfonctionprenant unentierenparamtreet ne
renvoyantrien.
Note: Lesparamtresconstantsdetyperfrencenepeuvent pastreinitialissavecune
donneimmdiateouunedonnetemporairelorsdelinstanciationdutemplate.VoirlaSection
12.4pourplusdedtailssurlinstanciationdes template .

12.3.Fonctionsetclassestemplate
template suit engnral ladclarationou
Aprsladclarationdunoudeplusieursparamtres
ladfinitiondunefonctionouduneclasse template. Danscettedfinition, lestypesgnriques
peuventtreutilissexactementcommesilsagissaitdetypesnormaux.Lesconstantes template
peuventtreutilisesdanslafonctionoulaclasse template commedesconstanteslocales.

12.3.1.Fonctionstemplate
Ladclarationet ladfinitiondesfonctions template sefait exactement commesi lafonction
taitunefonctionnormale, ceciprsquelledoittreprcdedeladclarationdesparamtres
template.Lasyntaxedunedclarationdefonction template estdonclasuivante:
template <paramtres_template>
typefonction(paramtres_fonction);

181

Chapitre12.Lestemplate
o paramtre_template estlalistedesparamtres template et paramtres_fonction estla
listedesparamtresdelafonction fonction. type estletypedelavaleurderetourdelafonction,
cepeuttreundestypesgnriquesdelalistedesparamtres template.
Touslesparamtres template quisontdestypesdoiventtreutilissdanslalistedesparamtresde
lafonction,moinsquuneinstanciationexplicitedelafonctionnesoitutilise.Celapermetaucom
pilateurderaliserlidentificationdestypesgnriquesaveclestypesutiliserlorsdelinstanciation
delafonction.VoirlaSection12.4pourplusdedtailscesujet.
Ladfinitiondunefonction template sefaitcommeunedclarationaveclecorpsdelafonction.
Ilestalorspossibledyutiliserlesparamtres template commesilstaientdestypesnormaux:
desvariablespeuventtredclaresavecuntypegnrique,etlesconstantestemplate peuventtre
utilisescommedesvariablesdfinieslocalement aveclaclassedestockageconst. Lesfonctions
template scriventdoncexactementcommedesfonctionsclassiques.
Exemple124.Dfinitiondefonctiontemplate
template <classT >
TMin(Tx,Ty)
{
returnx <y?x:y;
}

Lafonction Min ainsidfiniefonctionneraparfaitementpourtouteclassepourlaquelleloprateur


<
estdfini.Lecompilateurdtermineraautomatiquementquelestloprateuremployerpourchaque
fonction Min quilrencontrera.
Lesfonctions template peuventtresurcharges, aussibienpardesfonctionsclassiquesquepar
dautresfonctions template.Lorsquilyaambigutentreunefonction template etunefonction
normalequilasurcharge,touteslesrfrencessurlenomcommuncesfonctionsserapporteront
lafonctionclassique.
Unefonction template peuttredclareamieduneclasse, template ounon,pourvuquecette
classenesoitpaslocale.Touteslesinstancesgnrespartirdunefonctionamie template sont
amiesdelaclassedonnantlamiti,etontdonclibreaccssurtouteslesdonnesdecetteclasse.

12.3.2.Lesclassestemplate
Ladclarationet ladfinitionduneclasse template sefont commecelles dunefonction
template : ellesdoivent treprcdesdeladclaration
template destypesgnriques. La
dclarationsuitdonclasyntaxesuivante:
template <paramtres_template>
class|struct|unionnom;

o paramtres_template estlalistedesparamtres template utilissparlaclasse


nom.

template

Laseuleparticularitdansladfinitiondesclasses template estquesilesmthodesdelaclassene


sontpasdfiniesdansladclarationdelaclasse,ellesdevrontellesaussitredclarestemplate :
template <paramtres_template>
typeclasse<paramtres>::nom(paramtres_mthode)
{
...
}

182

Chapitre12.Lestemplate
o paramtre_template reprsentelalistedesparamtres template delaclasse template
classe, nom reprsentelenomdelamthodedfinir,et
paramtres_mthode sesparamtres.
Il est absolument ncessairedanscecasdespcifier
touslesparamtres template delaliste
paramtres_template dansparamtres, sparspardesvirgules, afindecaractriserlefaitque
cest laclasse classe qui est template et quil nesagit pasdunemthode template dune
classenormale.Dunemaniregnrale,ilfaudratoujoursspcifierlestypesgnriquesdelaclasse
entrelessignesdinfrioritetdesupriorit, justeaprssonnom, chaquefoisquonvoudrala
rfrencer. Cettergleestcependantfacultativelorsquelaclasseestrfrencelintrieurdune
fonctionmembre.
Contrairementauxfonctions template nonmembres,lesmthodesdesclasses template peuvent
utiliserdestypesgnriquesdeleurclassesanspourautantquilssoientutilissdanslalistedeleurs
paramtres.Eneffet,lecompilateurdterminequelssontlestypesidentifierauxtypesgnriques
lorsdelinstanciationdelaclasse template,etnadoncpasbesoindeffectuercetteidentification
aveclestypesdesparamtresutiliss.VoirlaSection12.3.3pourplusdedtailscesujet.
Exemple125.Dfinitiondunepiletemplate
template <classT >
classStack
{
typedefstructstackitem
{
TItem;
//OnutiliseletypeTcomme
structstackitem*Next;//sictaituntypenormal.
}StackItem;
StackItem*Tete;
public:
//Lesfonctionsdelapile:
Stack(void);
Stack(constStack<T> &);
//Laclasseestrfrenceenindiquant
//sontypeentre < et > ("Stack<T>").
//Ici,cenestpasunencessit
//cependant.
~Stack(void);
Stack<T> &operator=(constStack<T> &);
voidpush(T);
Tpop(void);
boolis_empty(void)const;
voidflush(void);
};
//Pourlesfonctionsmembresdfiniesendehorsdeladclaration
//delaclasse,ilfautunedclarationdetypegnrique:
template <classT >
Stack<T>::Stack(void)//Laclasseestrfrenceenindiquant
//sontypeentre < et > ("Stack<T>").
//Cestimpratifendehorsdela
//dclarationdelaclasse.
{
Tete=NULL;
return;
}

183

Chapitre12.Lestemplate

template <classT >


Stack<T>::Stack(constStack<T> &Init)
{
Tete=NULL;
StackItem*tmp1=Init.Tete,*tmp2=NULL;
while(tmp1!=NULL)
{
if(tmp2==NULL)
{
Tete=newStackItem;
tmp2=Tete;
}
else
{
tmp2>Next=newStackItem;
tmp2=tmp2 >Next;
}
tmp2>Item=tmp1>Item;
tmp1=tmp1 >Next;
}
if(tmp2!=NULL)tmp2>Next=NULL;
return;
}
template <classT >
Stack<T>::~Stack(void)
{
flush();
return;
}
template <classT >
Stack<T> &Stack<T>::operator=(constStack
<T> &Init)
{
flush();
StackItem*tmp1=Init.Tete,*tmp2=NULL;
while(tmp1!=NULL)
{
if(tmp2==NULL)
{
Tete=newStackItem;
tmp2=Tete;
}
else
{
tmp2>Next=newStackItem;
tmp2=tmp2 >Next;
}
tmp2>Item=tmp1>Item;
tmp1=tmp1 >Next;
}
if(tmp2!=NULL)tmp2>Next=NULL;
return*this;
}

184

Chapitre12.Lestemplate
template <classT >
voidStack<T>::push(TItem)
{
StackItem*tmp=newStackItem;
tmp>Item=Item;
tmp>Next=Tete;
Tete=tmp;
return;
}
template <classT >
TStack <T>::pop(void)
{
Ttmp;
StackItem*ptmp=Tete;
if(Tete!=NULL)
{
tmp=Tete>Item;
Tete=Tete >Next;
deleteptmp;
}
returntmp;
}
template <classT >
boolStack<T>::is_empty(void)const
{
return(Tete==NULL);
}
template <classT >
voidStack<T>::flush(void)
{
while(Tete!=NULL)pop();
return;
}

Lesclasses template peuventparfaitementavoirdesfonctionsamies,quecesfonctionssoientelles


mmes template ounon.

12.3.3.Fonctionsmembrestemplate
Lesdestructeursmispart, lesmthodesduneclassepeuventtre template, quelaclasseelle
mmesoit template ounon,pourvuquelaclassenesoitpasuneclasselocale.
Lesfonctionsmembres template peuventapparteniruneclasse
male.

template ouuneclassenor

Lorsquelaclasselaquelleellesappartiennentnestpas template,leursyntaxeestexactementla
mmequepourlesfonctions template nonmembre.

185

Chapitre12.Lestemplate
Exemple126.Fonctionmembretemplate
classA
{
inti;
//Valeurdelaclasse.
public:
template <classT >
voidadd(Tvaleur);
};
template <classT >
voidA::add(Tvaleur)
{
i=i+((int)valeur);
return;
}

//AjoutevaleurA::i.

Si, enrevanche, laclassedontlafonctionmembrefaitpartieestelleaussi template, ilfautsp


cifierdeuxfoislasyntaxe template : unefoispourlaclasse, et unefoispourlafonction. Si la
fonctionmembre template estdfinielintrieurdelaclasse, ilnestpasncessairededonner
lesparamtres template delaclasse,etladfinitiondelafonctionmembre template sefaitdonc
exactementcommecelledunefonction template classique.
Exemple127.Fonctionmembretemplateduneclassetemplate
template<classT >
classChaine
{
public:
//Fonctionmembretemplatedfinie
//lextrieurdelaclassetemplate:
template<classT2> intcompare(constT2&);
//Fonctionmembretemplatedfinie
//lintrieurdelaclassetemplate:
template<classT2>
Chaine(constChaine<T2> &s)
{
//...
}
};
//lextrieurdelaclassetemplate,ondoitdonner
//lesdclarationstemplatepourlaclasse
//etpourlafonctionmembretemplate:
template<classT > template<classT2>
intChaine<T>::compare(constT2&s)
{
//...
}

Lesfonctionsmembresvirtuellesnepeuventpastretemplate.Siunefonctionmembre template
alemmenomquunefonctionmembrevirtuelleduneclassedebase, elleneconstituepasune
redfinitiondecettefonction.Parconsquent,lesmcanismesdevirtualitsontinutilisablesavecles

186

Chapitre12.Lestemplate
fonctionsmembres template.Onpeutcontournerceproblmedelamaniresuivante:ondfinira
unefonctionmembrevirtuellenon template quiappelleralafonctionmembre template.
Exemple128.Fonctionmembretemplateetfonctionmembrevirtuelle
classB
{
virtualvoidf(int);
};
classD:publicB
{
template <classT >
voidf(T);
//CettefonctionneredfinitpasB::f(int).
voidf(inti)
{
f<>(i);
return;
}

//CettefonctionsurchargeB::f(int).
//Elleappelledelafonctiontemplate.

};

Danslexempleprcdent,onestobligdeprciserquelafonctionappelerdanslafonctionvirtuelle
estlafonction template,etquilnesagitdoncpasdunappelrcursifdelafonctionvirtuelle.Pour
cela,onfaitsuivrelenomdelafonction template dunepairedesignesinfrieuretsuprieur.
Plusgnralement,siunefonctionmembre template duneclassepeuttrespcialiseenunefonc
tionquialammesignaturequuneautrefonctionmembredelammeclasse,etquecesdeuxfonc
tionsontlemmenom,touterfrencecenomutiliseralafonctionnon template.Ilestpossible
template
depasseroutrecettergle, conditiondedonnerexplicitementlalistedesparamtres
entrelessignesinfrieuretsuprieurlorsdelappeldelafonction.
Exemple129.Surchargedefonctionmembreparunefonctionmembretemplate
#include <iostream>
usingnamespacestd;
structA
{
voidf(int);
template <classT >
voidf(T)
{
cout << "Template" << endl;
}
};
//Fonctionnontemplate:
voidA::f(int)
{
cout << "Nontemplate" << endl;
}
//Fonctiontemplate:

187

Chapitre12.Lestemplate
template <>
voidA::f<int>(int)
{
cout << "Spcialisationf <int>" << endl;
}
intmain(void)
{
Aa;
a.f(1);
//Appeldelaversionnontemplatedef.
a.f(c); //Appeldelaversiontemplatedef.
a.f<>(1);//Appeldelaversiontemplatespcialisedef.
return0;
}

Pourplusdedtailssurlaspcialisationdes template,voirlaSection12.5.

12.4.Instanciationdestemplate
Ladfinitiondesfonctionsetdesclasses template negnreaucuncodetantquetouslesparamtres
template nontpasprischacununevaleurspcifique.Ilfautdonc,lorsdelutilisationdunefonction
ouduneclasse template,fournirlesvaleurspourtouslesparamtresquinontpasdevaleurpar
dfaut.Lorsquesuffisammentdevaleurssontdonnes,lecodeestgnrpourcejeudevaleurs.On
appellecetteoprationlinstanciationdestemplate.
Plusieurs possibilits sont offertes pour parvenir ce rsultat : linstanciationimplicite
linstanciationexplicite.

et

12.4.1.Instanciationimplicite
Linstanciationimpliciteestutiliseparlecompilateurlorsquilrencontreuneexpressionquiutilise
pourlapremirefoisunefonctionouuneclasse template,etquildoitlinstancierpourcontinuer
sontravail.Lecompilateursebasealorssurlecontextecourantpourdterminerlestypesdespara
mtres template utiliser.Siaucuneambigutnalieu,ilgnrelecodepourcejeudeparamtres.
Ladterminationdestypesdesparamtres template peutsefairesimplement,outredduitede
lexpressioncompiler.Parexemple,lesfonctionsmembres template sontinstanciesenfonction
templateMin dfiniedans
dutypedeleursparamtres. Silonreprendlexempledelafonction
lExemple124,cestsonutilisationdirectequiprovoqueuneinstanciationimplicite.
Exemple1210.Instanciationimplicitedefonctiontemplate
inti=Min(2,3);

Danscetexemple,lafonction Min estappeleaveclesparamtres 2 et 3. Commecesentierssont


touslesdeuxdetypeint,lafonction templateMin estinstanciepourletypeint.Partoutdansla
dfinitionde Min,letypegnriqueTestdoncremplacparletypeint.
Silonappelleunefonction template avecunjeudeparamtresquiprovoqueuneambigut, le
compilateursignaleuneerreur.Cetteerreurpeuttreleveensurchargeantlafonctiontemplate par
unefonctionquiacceptelesmmesparamtres.Parexample,lafonction templateMinnepeutpas
treinstanciedanslecodesuivant:

188

Chapitre12.Lestemplate
inti=Min(2,3.0);

parcequelecompilateurnepeutpasdterminersiletypegnriqueTdoitprendrelavaleurintou
double. Ilyadoncuneerreur, saufsiunefonction Min(int,double) estdfiniequelquepart.
Pourrsoudrecetypedeproblme,ondevraspcifiermanuellementlesparamtres template dela
fonction,lorsdelappel.Ainsi,laligneprcdentecompilesionlarcritcommesuit:
inti=Min<int>(2,3.0);

danscetexemple,leparamtre template estforcint,et 3.0 estconvertienentier.


Onprendragardeaufaitquelecompilateurutiliseunepolitiqueminimalistepourlinstanciationim
plicitedes template.Celasignifiequilnecreraquelecodencessairepourcompilerlexpression
quiexigeuneinstanciationimplicite. Parexemple, ladfinitiondunobjetduneclasse template
dont touslestypesdfinisprovoquelinstanciationdecetteclasse,
maisladfinitiondunpoin
teursurcetteclassenelefaitpas.Linstanciationauralieulorsquundrfrencementserafaitpar
lintermdiairedecepointeur.Demme,seuleslesfonctionnalitsutilisesdelaclasse template
seronteffectivementdfiniesdansleprogrammefinal.
Parexemple,dansleprogrammesuivant:
#include <iostream>
usingnamespacestd;
template <classT >
classA
{
public:
voidf(void);
voidg(void);
};
//DfinitiondelamthodeA<T>::f():
template <classT >
voidA <T>::f(void)
{
cout << "A<T>::f()appele" << endl;
}
//OnnedfinitpaslamthodeA <T>::g()...
intmain(void)
{
A<char> a;
a.f();
return0;
}

//InstanciationdeA <char>.
//InstanciationdeA <char>::f().

seulelamthode f delaclasse template Aestinstancie,carcestlaseulemthodeutilisecet


endroit. Ceprogrammepourradoncparfaitementtrecompil, mmesilamthode g napast
dfinie.

189

Chapitre12.Lestemplate

12.4.2.Instanciationexplicite
Linstanciationexplicitedes template est unetechniquepermettant auprogrammeur deforcer
linstanciationdes template danssonprogramme.Pourraliseruneinstanciationexplicite,ilfaut
spcifierexplicitementtouslesparamtres template utiliser.Celasefaitsimplementendonnant
ladclarationdu template,prcdeparlemotcl template :
templatenom<valeur[,valeur[...]]>;

Parexemple, pourforcerlinstanciationdunepiletellequecelledfiniedanslExemple125,
faudraprciserletypedeslmentsentrecrochetsaprslenomdelaclasse:
templateStack<int>;

il

//InstancielaclasseStack<int>.

Cettesyntaxepeuttresimplifiepourlesfonctions template,conditionquetouslesparamtres
template puissenttredduitsparlecompilateurdestypesdesparamtresutilissdansladclara
tiondelafonction.Ainsi,ilestpossibledeforcerlinstanciationdelafonction templateMindela
maniresuivante:
templateintMin(int,int);

Danscetexemple,lafonction templateMinestinstanciepourletypeint,puisquesesparamtres
sontdecetype.
Lorsquunefonctionouuneclassetemplate adesvaleurspardfautpoursesparamtrestemplate,
ilnestpasncessairededonnerunevaleurpourcesparamtres.Sitouteslesvaleurspardfautsont
utilises, lalistedesvaleurspeut trevide(maislessignesdinfrioritet
desuprioritdoivent
malgrtouttreprsents).
Exemple1211.Instanciationexplicitedeclassetemplate
template<classT=char>
classChaine;
templateChaine<>;

//InstanciationexplicitedeChaine

<char>.

12.4.3.Problmessoulevsparlinstanciationdes
template
Les template doiventimprativementtredfinislorsdeleurinstanciationpourquelecompila
teurpuissegnrerlecodedelinstance.Celasignifiequelesfichiersdenttedoiventcontenirnon
seulementladclaration,maisgalementladfinitioncompltedes template.Celaaplusieursin
convnients.Lepremierestbienentenduquelonnepeutpasconsidrerles template commeles
fonctionsetlesclassesnormalesdulangage,pourlesquelsilestpossibledesparerladclarationde
ladfinitiondansdesfichiersspars.Ledeuximeinconvnientestquelesinstancesdes template
sontcompilesplusieursfois,cequidiminuedautantpluslesperformancesdescompilateurs.Enfin,
cequiestleplusgrave,cestquelesinstancesdes template sontenmultiplesexemplairesdansles
fichiersobjetsgnrsparlecompilateur,etaccroissentdonclatailledesfichiersexcutableslissue

190

Chapitre12.Lestemplate
delditiondeliens.Celanestpasgnantpourlespetitsprogrammes,maispeutdevenirrdhibitoire
pourlesprogrammesassezgros.
Lepremierproblmenestpastropgnant,carilrduitlenombredefichierssources,cequinesten
gnralpasunemauvaisechose.Notezgalementqueles template nepeuventpastreconsidrs
commedesfichierssourcesclassiques,puisquesansinstanciation,ilsnegnrentaucuncodemachine
(cesontdesclassesdeclasses,oumtaclasses).Maisceproblmepeutdevenirennuyantdans
lecasdebibliothques template critesetvenduespardessocitsdsireusesdeconserverleur
savoirfaire.Pourrsoudreceproblme,lelangagedonnelapossibilitdexporterlesdfinitionsdes
template dansdesfichierscomplmentaires.NousverronslamaniredeprocderdanslaSection
12.7.
Ledeuximeproblmepeuttrersoluaveclexportationdestemplate,oupartoutautretechnique
doptimisationdescompilateurs.Actuellement,laplupartdescompilateurssontcapablesdegnrer
desfichiersdentteprcompils,quicontiennentlersultatdelanalysedesfichiersdenttedj
lus.Cettetechniquepermetdediminuerconsidrablementlestempsdecompilation,maisncessite
souventdutilisertoujourslemmefichierdentteaudbutdesfichierssources.
Letroisimeproblmeestengnralrsolupardestechniquesvaries,quincessitentdestraitements
complexesdanslditeurdeliensoulecompilateur.Latechniquelaplussimple,utiliseparlaplupart
descompilateursactuels, passeparunemodificationdelditeurdelienspourquil regroupeles
diffrentesinstancesdesmmes template. Dautrescompilateurs, plusrares, grentunebasede
donnesdanslaquellelesinstancesde template gnreslorsdelacompilationsontstockes.Lors
delditiondeliens,lesinstancesdecettebasesontajouteslalignedecommandedelditeurde
liensafindersoudrelessymbolesnondfinis.Enfin,certainscompilateurspermettentdedsactiver
lesinstanciationsimplicitesdes template.Celapermetdelaisserauprogrammeurlaresponsabilit
delesinstanciermanuellement, laidedinstanciationsexplicites. Ainsi, les template peuvent
ntredfiniesquedansunseulfichiersource,rservceteffet.Cettederniresolutionestdeloin
laplussre,etilestdoncrecommanddcrireuntelfichierpourchaqueprogramme.
Ce paragraphe vous a prsent trois des principauxproblmes soulevs par lutilisationdes
template, ainsi quelessolutionslespluscourantesqui
yont tapportes. Il est vivement
recommanddeconsulterladocumentationfournieaveclenvironnementdedveloppementutilis,
afinlafoisderduirelestempsdecompilationetdoptimiserlesexcutablesgnrs.

12.5.Spcialisationdestemplate
Jusquprsent,nousavonsdfinilesclassesetlesfonctions template dunemanireunique,pour
touslestypesettouteslesvaleursdesparamtres template.Cependant,ilpeuttreintressantde
dfiniruneversionparticulireduneclasseoudunefonctionpourunjeuparticulierdeparamtres
template.
Parexemple, lapiledelExemple125peut treimplmentebeaucoupplusefficacement si elle
stockedespointeurspluttquedesobjets,saufsilesobjetssontpetits(ouappartiennentundestypes
prdfinisdulangage).Ilpeuttreintressantdemanipulerlespointeursdemaniretransparenteau
niveaudelapile,pourquelamthode pop renvoietoujoursunobjet,quelapilestockedespointeurs
oudesobjets.Afinderalisercela,ilfautdonnerunedeuximeversiondelapilepourlespointeurs.
LeC++permettoutcela:lorsquunefonctionouuneclasse template atdfinie,ilestpossible
delaspcialiserpouruncertainjeudeparamtres template.Ilexistedeuxtypesdespcialisation:
lesspcialisationstotales,quisontlesspcialisationspourlesquellesilnyaplusaucunparamtre
template (ilsonttousunevaleurbiendtermine),etlesspcialisationspartielles,pourlesquelles
seulsquelquesparamtres template ontunevaleurfixe.

191

Chapitre12.Lestemplate

12.5.1.Spcialisationtotale
Lesspcialisationstotalesncessitentdefournirlesvaleursdesparamtres template,sparespar
desvirgulesetentrelessignesdinfrioritetdesupriorit,
aprslenomdelafonctionoudela
classe template.Ilfautfaireprcderladfinitiondecettefonctionoudecetteclasseparlaligne
suivante:
template <>

quipermetdesignalerquelalistedesparamtres
doncquelaspcialisationesttotale).

template pourcettespcialisationestvide(et

Parexemple,silafonction Min dfiniedanslExemple124doittreutilisesurunestructureStruc


tureetsebasersurundeschampsdecettestructurepoureffectuerlescomparaisons,ellepourratre
spcialisedelamaniresuivante:
Exemple1212.Spcialisationtotale
structStructure
{
intClef;
void*pData;
};

//Clefpermettantderetrouverdesdonnes.
//Pointeursurlesdonnes.

template <>
StructureMin<Structure>(Structures1,Structures2)
{
if(s1.Clef>s2.Clef)
returns1;
else
returns2;
}
template ne
Note:Pourquelquescompilateurs,lalignedclarantlalistevidedesparamtres
doitpastrecrite.Ondoitdoncfairedesspcialisationstotalesanslemotcl template.Ce
comportementnestpasceluispcifiparlanorme,etlecodecritpourcescompilateursnest
doncpasportable.

12.5.2.Spcialisationpartielle
Lesspcialisationspartiellespermettentdedfinirlimplmentationdunefonctionouduneclasse
template pourcertainesvaleursdeleursparamtres template et degarderdautresparamtres
indfinis.Ilestmmepossibledechangerlanaturedunparamtre template (cestdireprciser
sil sagit dunpointeurounon)et deforcerlecompilateurprendreuneimplmentationplutt
quuneautreselonquelavaleurutilisepourceparamtreestellemmeunpointeurounon.
template
Commepourlesspcialisationstotales,ilestncessairededclarerlalistedesparamtres
utilissparlaspcialisation.Cependant,ladiffrencedesspcialisationstotales,cettelistenepeut
plustrevide.

Commepourlesspcialisationstotales,ladfinitiondelaclasseoudelafonction template doituti


template
liserlessignesdinfrioritetdesuprioritpourdonnerlalistedesvaleursdesparamtres
pourlaspcialisation.

192

Chapitre12.Lestemplate
Exemple1213.Spcialisationpartielle
//Dfinitionduneclassetemplate:
template <classT1,classT2,intI >
classA
{
};
//Spcialisationn 1delaclasse:
template <classT,intI >
classA <T,T*,I >
{
};
//Spcialisationn 2delaclasse:
template <classT1,classT2,intI >
classA <T1*,T2,I >
{
};
//Spcialisationn 3delaclasse:
template <classT >
classA <int,T*,5 >
{
};
//Spcialisationn 4delaclasse:
template <classT1,classT2,intI >
classA <T1,T2*,I >
{
};
template peut
Onnoteraquelenombredesparamtres template dclarslasuitedumotcl
varier, maisquelenombredevaleursfourniespourlaspcialisationest
toujoursconstant (dans
lexempleprcdent,ilyenatrois).

Lesvaleursutilisesdanslesidentificateurstemplate desspcialisationsdoiventrespecterlesrgles
suivantes:

unevaleurnepeutpastreexprimeenfonctiondunparamtre

template delaspcialisation;

template <intI,intJ >


structB
{
};
template <intI >
structB <I,I*2>
{
};

//Erreur!
//Spcialisationincorrecte!

letypedunedesvaleursdelaspcialisationnepeutpasdpendredunautreparamtre;
template <classT,Tt >
structC
{
};

193

Chapitre12.Lestemplate

template <classT >


structC <T,1 >;
//Erreur!
//Spcialisationincorrecte!

lalistedesargumentsdelaspcialisationnedoitpastreidentiquelalisteimplicitedeladcla
ration template correspondante.

Enfin,lalistedesparamtres template deladclarationdunespcialisationnedoitpascontenir


desvaleurspardfaut.Onnepourraitdailleurslesutiliserenaucunemanire.

12.5.3.Spcialisationdunemthodeduneclassetemplate
Laspcialisationpartielleduneclassepeutparfoistreassezlourdeemployer,enparticuliersila
structurededonnesquellecontientnechangepasentrelesversionsspcialises.Danscecas,ilpeut
treplussimpledenespcialiserquecertainesmthodesdelaclasseetnonlaclassecomplte.Cela
permetdeconserverladfinitiondesmthodesquinontpaslieudtremodifiespourlesdiffrents
types,etdviterdavoirredfinirlesdonnesmembresdelaclasselidentique.
Lasyntaxepermettantdespcialiserunemthodeduneclasse template esttrssimple. Ilsuffit
template normale, etdelaspcialiseren
eneffetdeconsidrerlamthodecommeunefonction
prcisantlesparamtres template utiliserpourcettespcialisation.
Exemple1214.Spcialisationdefonctionmembredeclassetemplate
#include <iostream>
usingnamespacestd;
template <classT >
classItem
{
Titem;
public:
Item(T);
voidset(T);
Tget(void)const;
voidprint(void)const;
};
template <classT >
Item<T>::Item(Ti)
{
item=i;
}
//Accesseurs:
template <classT >
voidItem<T>::set(Ti)
{
item=i;
}

194

//Constructeur

Chapitre12.Lestemplate
template <classT >
TItem <T>::get(void)const
{
returnitem;
}
//Fonctiondaffichagegnrique:
template <classT >
voidItem<T>::print(void)const
{
cout << item << endl;
}
//Fonctiondaffichagespcialiseexplicitementpourletypeint*
//etlamthodeprint:
template <>
voidItem<int* >::print(void)const
{
cout << *item << endl;
}

12.6.Motcltypename
Nousavonsdjvuquelemotcl typename pouvaittreutilispourintroduirelestypesgnriques
danslesdclarations template.Cependant,ilpeuttreutilisdansunautrecontextepourintroduire
lesidentificateursdetypesinconnusdansles template.Eneffet,untypegnriquepeuttrsbien
treuneclassedfinieparlutilisateur,lintrieurdelaquelledestypessontdfinis.Afindepouvoir
utilisercestypesdanslesdfinitionsdes template,ilestncessairedutiliserlemotcl typename
pourlesintroduire,carapriorilecompilateurnesaitpasqueletypegnriquecontientladfinition
dunautretype.Cemotcldoittreplacavantlenomcompletdutype:
typenameidentificateur

Le mot cl typename est donc utilis pour signaler au compilateur que lidentificateur
identificateur estuntype.
Exemple1215.Motcltypename
classA
{
public:
typedefintY;
};
template <classT >
classX
{
typenameT::Yi;

//YestuntypedfinidanslaclasseA.

//LaclassetemplateXsupposequele
//typegnriqueTdfinisseuntypeY.

};

195

Chapitre12.Lestemplate

X<A> x;

//Apeutservirinstancieruneclasse
//partirdelaclassetemplateX.

12.7.Fonctionsexportes
Commeonlavu, lesfonctionsetclasses template sonttoutesinstancieslorsquellessontren
contrespourlapremirefoisparlecompilateuroulorsquelalistedeleursparamtresestfournie
explicitement.
Cettergleauneconsquencemajeure:ladfinitioncompltedesfonctionsetdesclasses template
doittreinclusedanschacundesfichiersdanslequelellessontutilises.Engnral,lesdclarationset
lesdfinitionsdesfonctionsetdesclasses template sontdoncregroupesensembledanslesfichiers
dentte(etlecodenesetrouvepasdansunfichierC++).Celaestlafoistrslent(ladfinitiondoit
trerelueparlecompilateurchaquefoisquun template estutilis)etnepermetpasdeprotgerle
savoirfairedesentreprisesquiditentdesbibliothques template,puisqueleurcodeestaccessible
toutlemonde.
Afindersoudreces problmes, leC++permet decompiler les fonctions et les classes
template, et ainsi dviterlinclusionsystmatiquedeleurdfinitiondanslesfichierssources.
Cettecompilationsefaitlaidedumotcl export.
Pourparvenircersultat, vousdevezdclarer export lesfonctionsetlesclasses template
concernes. Ladclarationduneclasse templateexportrevient dclarer export toutesses
fonctionsmembresnon inline,toutessesdonnesstatiques,toutessesclassesmembresettoutes
sesfonctionsmembres template nonstatiques.Siunefonction template estdclarecommetant
inline,ellenepeutpastredetype export.
Lesfonctionsetlesclasses template quisontdfiniesdansunespacedenommageanonymene
peuventpastredclares export.VoirleChapitre11plusdedtailssurlesespacesdenommage.
Exemple1216.Motclexport
exporttemplate <classT >
voidf(T);
//Fonctiondontlecodenestpasfourni
//danslesfichiersquilutilisent.

Danscetexemple,lafonction f estdclare export.Sadfinitionestfourniedansunautrefichier,


etnapasbesoindtrefourniepourque f soitutilisable.
Lesdfinitionsdesfonctionsetdesclassesdclares export doiventellesaussiutiliserlemotcl
export.Ainsi,ladfinitionde f pourraressemblerauxlignessuivantes:
exporttemplate <classT >
voidf(Tp)
{
//Corpsdelafonction.
return;
}

Note:Aucuncompilateurnegrelemotcl export cejour.

196

II.LabibliothquestandardC++

ToutcommepourlelangageC,pourlequeluncertainnombredefonctionsonttdfiniesetstandar
disesetconstituentlabibliothqueC,unebibliothquedeclassesetdefonctionsatspcifiepour
lelangageC++. Cettebibliothqueestlersultatdelvolutiondeplusieursbibliothques, parfois
dveloppesindpendammentparplusieursfournisseursdenvironnementsC++,quionttfusion
nesetnormalisesafindegarantirlaportabilitdesprogrammesquilesutilisent.Unedesprinci
palesbriquesdecettebibliothqueestsansaucundoutelaSTL(abrviationdeStandardTemplate
Library),telpointquilyasouventconfusionentrelesdeux.
CettepartieapourbutdeprsenterlesprincipalesfonctionnalitsdelabibliothquestandardC++.
Bienentendu,ilesthorsdequestiondedcrirecompltementchaquefonctionouchaquedtaildu
fonctionnementdelabibliothquestandard,carcelarendraitillisiblesetincomprhensibleslesex
plications.Cependant,lesinformationsdebasevousserontdonnesafindevouspermettredutiliser
efficacement labibliothquestandardC++et decomprendrelesfonctionnalitslesplusavances
lorsquevousvousyintresserez.
LabibliothquestandardC++estrellementunsujetdetaille. titreindicatif, sadescriptionest
aussivolumineusequecelledulangageluimmedanslanormeC++.Maiscenestpastout,ilfaut
imprativementavoircomprisenprofondeurlesfonctionnalitslesplusavancesduC++pourappr
hendercorrectementlabibliothquestandard.Enparticulier,touslesalgorithmesettouteslesclasses
fourniesparlabibliothquesontsusceptiblesdetravaillersurdesdonnesdetypearbitraire.Labi
bliothqueutilisedonccompltementlanotiondetemplate,etsebasesurplusieursabstractionsdes
donnesmanipulesetdeleurstypesafinderendregnriquelimplmentationdesfonctionnalits.
Deplus,labibliothqueutiliselemcanismedesexceptionsafindesignalerleserreursquipeuventse
produirelorsdelexcutiondesmthodesdesesclassesetdesesfonctions.Enfin,uncertainnombre
denotionsalgorithmiquesavancessontutilisesdanstoutelabibliothque.Laprsentationquisera
faiteseradoncprogressive,toutenessayantdeconserverunordrelogique.Toutcommepourlapar
tieprcdente,ilestprobablequeplusieurslecturesserontncessairesauxdbutantspourassimiler
touteslessubtilitsdelabibliothque.
Lepremierchapitredecettepartie(Chapitre13)prsentelesnotionsdebasequisontutilisesdans
toutelalibraire:encapsulationdesfonctionsdelabibliothqueCclassique,classesdetraitspourles
typesdebase,notionditrateurs,defoncteurs,dallocateursmmoireetdecomplexitalgorithmique.
LeChapitre14prsentelestypescomplmentairesquelabibliothquestandardC++dfinit
pour
faciliterlavieduprogrammeur. Leplusimportantdecestypesestsansdoutelaclassedegestion
deschanesdecaractresbasic_string.LeChapitre15prsentelesnotionsdefluxdentre/sortie
standards, et lanotiondetamponpourcesflux. Lesmcanismesdelocalisation(cestdireles
fonctionsdeparamtrageduprogrammeenfonctiondesconventionsetdesprfrencesnationales)
serontdcritsdansleChapitre16.LeChapitre17estsansdoutelundesplusimportants,puisquil
prsentetouslesconteneursfournisparlabibliothquestandard. Enfin, leChapitre18dcrit les
principauxalgorithmesdelabibliothque,quipermettentdemanipulerlesdonnesstockesdansles
conteneurs.
LesinformationsdcritesicisontbasessurlanormeISO14882dulangageC++,etnonsurlaralit
desenvironnementsC++actuels.Ilestdoncfortementprobablequebonnombredexemplesfournis
icinesoientpasutilisablestelsquelssurlesenvironnementsdedveloppementexistantssurlemar
ch,bienqueloncommencevoirapparatredesenvironnementspresquetotalementrespectueuxde
lanormemaintenant.Delgresdiffrencesdanslinterfacedesclassesdcritespeuventgalement
apparatreetncessiterlamodificationdecesexemples.Cependant,terme,touslesenvironnements
dedveloppementrespecterontlesinterfacesspcifiesparlanorme,etlesprogrammesutilisantla
bibliothquestandardserontrellementportablesauniveausource.

Chapitre13.Servicesetnotionsdebasedela
bibliothquestandard
LabibliothquestandardC++fournit uncertainnombredefonctionnalitsdebasesurlesquelles
touteslesautresfonctionnalitsdelabibliothquesappuient.
Cesfonctionnalitsapparaissent
commedesclassesdencapsulationdelabibliothqueCetdesclassesdabstractiondesprincipales
constructionsdulangage. Cesderniresutilisent desnotionstrsvoluespour permettreune
encapsulationrellementgnriquedestypesdebase.Dautrepart,labibliothquestandardutilise
lanotiondecomplexitalgorithmiquepourdfinirlescontraintesdeperformancedesoprations
ralisablessursesstructuresdedonnesainsiquesursesalgorithmes. Bienquecomplexes, toutes
cesnotionssontomniprsentesdanstoutelabibliothque,aussiestilextrmementimportantdeles
comprendreendtail.Cechapitreapourbutdevouslesprsenteretdelesclaircir.

13.1.EncapsulationdelabibliothqueCstandard
LabibliothqueCdfinitungrandnombredefonctionsCstandards, quelabibliothquestandard
C++reprendsoncompteetcompltepartoutessesfonctionnalitsavances.Pourbnficierdeces
fonctions,ilsuffitsimplementdinclurelesfichiersdenttedelabibliothqueC,toutcommeonle
faisaitaveclesprogrammesCclassiques.
Toutefois,lesfonctionsainsidclaresparcesenttesapparaissentdanslespacedenommageglobal,
cequirisquedeprovoquerdesconflitsdenomsavecdesfonctionshomonymes(rappelonsqueles
fonctionsCnesontpassurchargeables).Parconsquent,etdansunsoucidhomognitaveclereste
desfonctionnalitsdelabibliothqueC++,unjeudenttescomplmentairesatdfinipourles
fonctionsdelabibliothqueC.Cesenttesdfinissenttousleurssymbolesdanslespacedenommage
std::,quiestrservpourlabibliothquestandardC++.
CesenttessedistinguentdesfichiersdenttedelabibliothqueCparlefaitquilsneportentpas
dextension .h etparlefaitqueleurnomestprfixparlalettrec.Lesenttesutilisablesainsisont
donclessuivants:
cassert
cctype
cerrno
cfloat
ciso646
climits
clocale
cmath
csetjmp
csignal
cstdarg
cstddef
cstdio
cstdlib
cstring
ctime
cwchar
cwctype

Parexemple, onpeutrcrirenotretoutpremierprogrammequelonafaitlaSection1.9dela
maniresuivante:
#include <cstdio>

199

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
longdoublex,y;
intmain(void)
{
std::printf("Calculdemoyenne\n");
std::printf("Entrezlepremiernombre:");
std::scanf("%Lf",&x);
std::printf("\nEntrezledeuximenombre:");
std::scanf("%Lf",&y);
std::printf("\nLavaleurmoyennede%Lfetde%Lfest%Lf.\n",
x,y,(x+y)/2);
return0;
}

Note:Lutilisationsystmatiqueduprfixestd:: peuttrenervantesurlesgrandsprogrammes.
Onauradoncintrt soit utiliserlesfichiersdentteclassiquesdelabibliothqueC, soit
inclureunedirective usingnamespacestd; pourintgrerlesfonctionnalitsdelabibliothque
standarddanslespacedenommageglobal.
Remarquezquelanormenesupposepasquecesenttessoientdesfichiersphysiques.Les
dclarationsquilssont suppossfairepeuvent donctreraliseslavoleparlesoutilsde
dveloppement,etvousnelestrouverezpasforcmentsurvotredisquedur.

CertainesfonctionnalitsfourniesparlabibliothqueConttencapsulesdansdesfonctionnalits
quivalentesdelabibliothquestandardC++.Cestnotammentlecaspourlagestiondeslocaleset
lagestiondecertainstypesdedonnescomplexes.Cestgalementlecaspourladterminationdes
limitesdereprsentationquelestypesdebasepeuventavoir.Classiquement,ceslimitessontdfinies
pardesmacrosdanslesenttesdelabibliothqueC,maisellessontgalementaccessiblesautravers
delaclasse template numeric_limits,dfiniedanslentte limits :
//Typesdarrondispourlesflottants:
enumfloat_round_style
{
round_indeterminate
=1,
round_toward_zero
= 0,
round_to_nearest
= 1,
round_toward_infinity
=2,
round_toward_neg_infinity=3
};
template <classT >
classnumeric_limits
{
public:
staticconstboolis_specialized=false;
staticTmin()throw();
staticTmax()throw();
staticconstintdigits =0;
staticconstintdigits10=0;
staticconstboolis_signed =false;
staticconstboolis_integer=false;
staticconstboolis_exact =false;
staticconstintradix=0;
staticTepsilon()throw();

200

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
staticTround_error()throw();
staticconstintmin_exponent =0;
staticconstintmin_exponent10=0;
staticconstintmax_exponent =0;
staticconstintmax_exponent10=0;
staticconstboolhas_infinity =false;
staticconstboolhas_quiet_NaN=false;
staticconstboolhas_signaling_NaN=false;
staticconstboolhas_denorm
=false;
staticconstboolhas_denorm_loss =false;
staticTinfinity()throw();
staticTquiet_NaN()throw();
staticTsignaling_NaN()throw();
staticTdenorm_min()throw();
staticconstboolis_iec559 =false;
staticconstboolis_bounded=false;
staticconstboolis_modulo =false;
staticconstbooltraps
=false;
staticconstbooltinyness_before=false;
staticconstfloat_round_style
round_style=round_toward_zero;
};

Cetteclasse template nesertrienensoi.Enfait,elleestspcialisepourtouslestypesdebasedu


langage,etcesontcesspcialisationsquisontrellementutilises.Ellespermettentdobtenirtoutes
lesinformationspourchaquetypegrceleursdonnesmembresetleursmthodesstatiques.
Exemple131.Dterminationdeslimitesduntype
#include <iostream>
#include <limits>
usingnamespacestd;
intmain(void)
{
cout << numeric_limits<int>::min() << endl;
cout << numeric_limits<int>::max() << endl;
cout << numeric_limits<int>::digits << endl;
cout << numeric_limits<int>::digits10 << endl;
return0;
}

Ceprogrammedexempledterminelepluspetitetleplusgrandnombrereprsentableavecletype
entierint,ainsiquelenombredebitsutilisspourcoderleschiffresetlenombremaximaldechiffres
quelesnombresenbase10peuventavoirentantsrdepouvoirtrestockstelsquels.

13.2.Dfinitiondesexceptionsstandards
Labibliothquestandardutiliselemcanismedesexceptionsdulangagepoursignalerleserreursqui
peuventseproduirelexcutionauseindesesfonctions.Elledfinitpourcelauncertainnombre
declassesdexceptionsstandards,quetouteslesfonctionnalitsdelabibliothquesontsusceptibles
dutiliser.Cesclassespeuventtreutilisestellesquellesouservirdeclassesdebasedesclasses
dexceptionspersonnalisespourvospropresdveloppements.

201

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
Cesclassesdexceptionsontpresquetoutesdclaresdanslentte stdexcept, etdriventdela
classedebaseexception.Cettedernirenestpasdclaredanslemmeentteetnestpasutilise
directement,maisfournitlesmcanismesdebasedetouteslesexceptionsdelabibliothquestandard.
Elleestdclarecommesuitdanslentte exception :
classexception
{
public:
exception()throw();
exception(constexception&)throw();
exception&operator=(constexception&)throw();
virtual~exception()throw();
virtualconstchar*what()constthrow();
};

Outrelesconstructeurs, oprateursdaffectationet destructeursclassiques, cetteclassedfinitune


mthode what quiretourneunechanedecaractresstatique.Lecontenudecettechanedecarac
tresnest pasnormalis. Cependant, il sert gnralement dcrirelanaturedelerreurqui sest
produite.Cestunemthodevirtuelle,carelleestbienentendudestinetreredfinieparlesclasses
dexceptionspcialisespourlesdiffrentstypesderreurs.Notezquetouteslesmthodesdelaclasse
exceptionsontdclarescommenepouvantpaslancerdexceptionsellemmes,cequiestnaturel
puisquelonestdjentraindetraiteruneexceptionlorsquonmanipuledesobjetsdecetteclasse.
Lentte exception contientgalementladclarationdelaclassedexceptionbad_exception.Cette
classenest,elleaussi,pasutiliseentempsnormal.Leseulcasoellepeuttrelanceestdansle
std::unexpected
traitementdelafonctiondetraitementderreurquiestappeleparlafonction
lorsquuneexceptionaprovoqulasortiedunefonctionquinavaitpasledroitdelalancer.Laclasse
bad_exceptionestdclarecommesuitdanslentte exception :
classbad_exception:publicexception
{
public:
bad_exception()throw();
bad_exception(constbad_exception&)throw();
bad_exception&operator=(constbad_exception&)throw();
virtual~bad_exception()throw();
virtualconstchar*what()constthrow();
};

Notezquelexceptionbad_alloclanceparlesgestionnairesdemmoirelorsqueloprateur new ou
loprateur new[] napasrussifaireuneallocationnestpasdclaredanslentte stdexcept
nonplus.Sadclarationatplaceaveccelledesoprateursdallocationmmoire,danslentte
new.Cetteclassedrivetoutefoisdelaclasseexception,commelemontresadclaration:
classbad_alloc:publicexception
{
public:
bad_alloc()throw();
bad_alloc(constbad_alloc&)throw();
bad_alloc&operator=(constbad_alloc&)throw();
virtual~bad_alloc()throw();
virtualconstchar*what()constthrow();
};

202

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard

Lesautresexceptionssontclassesendeuxgrandescatgories.Lapremirecatgorieregroupetoutes
lesexceptionsdontlapparitiontraduitsansdouteuneerreurdeprogrammationdansleprogramme,
carellesnedevraientjamaisseproduirelexcution.Ilsagitdesexceptionsditesderreursdans
lalogiqueduprogrammeet,entantquetelles,driventdelaclassedexceptionlogic_error.Cette
classeestdclarecommesuitdanslentte stdexcept :
classlogic_error:publicexception
{
public:
logic_error(conststring&what_arg);
};

Ellenecontientquunconstructeur,permettantdedfinirlachanedecaractresquiserarenvoye
parlamthodevirtuelle what. Ceconstructeurprendenparamtrecettechanedecaractressous
laformedunobjetdelaclassestring. Cetteclasseestdfinieparlabibliothquestandardafinde
faciliterlamanipulationdeschanesdecaractresetseradcriteplusendtaildanslaSection14.1.
Lesclassesdexceptionquidriventdelaclasselogic_errordisposentgalementdunconstructeur
similaire.Cesclassessontlessuivantes:

laclassedomain_error,quispcifiequunefonctionatappeleavecdesparamtressurlesquels
ellenest pasdfinie. Il faut contrlerlesvaleursdesparamtresutiliseslorsdelappel
dela
fonctionquialanccetteexception;

laclasseinvalid_argument, qui spcifiequundesargumentsdunemthodeoudunefonction


nestpasvalide. Cetteerreurarrivelorsquonutilisedesvaleursdeparamtresquinentrentpas
danslecadredefonctionnementnormaldelamthodeappele;celatraduitsouventunemauvaise
utilisationdelafonctionnalitcorrespondante;

laclasselength_error,quiindiquequundpassementdecapacitmaximaledunobjetatralis.
Cesdpassementsseproduisentdanslesprogrammesbogus,quiessaientdutiliserunefonction
nalitaudeldeslimitesquiavaienttfixespourelle;

laclasseout_of_range,quispcifiequunevaleursitueendehorsdelaplagedevaleursautorises
atutilise.Cetypederreursignifiesouventquelesparamtresutilisspourunappeldefonction
nesontpascorrectsoupasinitialiss,etquilfautvrifierleurvalidit.

Ladeuximecatgoriedexceptionscorrespondauxerreursquinepeuventpastoujourstrecorriges
lorsdelcritureduprogramme, etquifontdoncpartiedesvnementsnaturelsquiseproduisent
lorsdesonexcution.Ellescaractrisentleserreursdexcution,etdriventdelaclassedexception
runtime_error.Cetteclasseestdclaredelamaniresuivantedanslentte stdexcept :
classruntime_error:publicexception
{
public:
runtime_error(conststring&what_arg);
};

Ellesutiliseexactementcommelaclasselogic_error.
Lesexceptionsdelacatgoriedeserreursdexcutionsontlessuivantes:

laclasserange_error,quisignifiequunevaleurestsortiedelaplagedevaleursdanslaquelleelle
devaitsetrouversuiteundbordementinternelabibliothque;

203

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard

laclasseoverflow_error,quisignifiequundbordementparvaleurssuprieuressestproduitdans
uncalculinternelabibliothque;

laclasseunderflow_error,quisignifiequundbordementparvaleursinfrieuressestproduitdans
uncalculinternelabibliothque.

13.3.Abstractiondestypesdedonnes:lestraits
Uncertainnombredeclassesoudalgorithmespeuventmanipulerdestypesayantunesignification
particulire. Parexemple, laclassestring, quenousverronsplusloin, manipuledesobjetsdetype
caractre. Enralit, cesclasseset cesalgorithmespeuvent travailleravecnimportequelstypes
pourvuquetouscestypessecomportentdelammemanire.LabibliothquestandardC++utilise
donclanotiondetraits, quipermetdedfinirlescaractristiquesdecestypes. Lestraitssont
dfinisdansdesclassesprvuescetusage.Lesclassesetlesalgorithmesstandardsnutilisentque
lesclassesdetraitspourmanipulerlesobjets, garantissantainsiuneabstractiontotalevisvisde
leurstypes.Ainsi,ilsuffitdecoderunespcialisationdelaclassedestraitspouruntypeparticulier
afindepermettresonutilisationdanslesalgorithmesgnriques.Labibliothquestandarddfinitbien
entendudesspcialisationspourlestypesdebasedulangage.
Parexemple,laclassededfinitiondestraitsdestypesdecaractresestlaclassetemplatechar_traits.
Ellecontientlesdfinitionsdestypessuivants:

letypechar_type,quiestletypereprsentantlescaractreseuxmmes;

letypeint_type,quiestuntypecapabledecontenirtouteslesvaleurspossiblespourlescaractres,
ycomprislavaleurspcialedumarqueurdefindefichier;

letypeoff_type,quiestletypepermettantdereprsenterlesdplacementsdansunesquencede
caractres,ainsiquelespositionsabsoluesdanscettesquence.Cetypeestsigncarlesdplace
mentspeuventtreralissaussibienversledbutdelasquencequeverslafin;

letypepos_type,quiestunsoustypedutypeoff_type,etquinestutilisquepourlesdplacements
danslesfonctionsdepositionnementdesfluxdelabibliothquestandard;

letypestate_type,quipermetdereprsenterltatcourantdunesquencedecaractresdansles
fonctionsdeconversion. Cetypeestutilisdanslesfonctionsdetranscodagedessquencesde
caractresdunencodageversunautre.

Note:Pourcomprendrelutilitdecederniertype,il fautsavoirquil existeplusieursmanires


decoderlescaractres.Laplupartdesmthodesutilisentunencodage taille fixe,ochaque
caractreestreprsentparunevaleurentireetuneseule.Cettetechniqueesttrspratique
pourlesjeuxdecaractrescontenantmoinsde256caractres,pourlesquelsunseul octetest
utilisparcaractre.Elleestgalementutilisepourlesjeuxdecaractresdemoinsde65536
caractres, car lutilisationde16bitspar
caractresest encoreraisonable. Enrevanche, les
caractresdesjeuxdecaractresorientauxsontcodsavecdesvaleursnumriquessuprieures
65536parlesencodagesstandards(Unicodeet ISO10646), et nepeuvent doncpastre
stocksdanslestypescharouwchar_t.Pourcesjeuxdecaractres,onutilisedoncsouventdes
encodages taille variable,ochaquecaractrepeuttrereprsentparunouplusieursoctets
selonsanatureetventuellementselonsapositiondanslachanedecaractres.
Pourcesencodagestaillevariable, il est vident quelepositionnement danslessquences
decaractressefait enfonctionducontextedelachane, savoirenfonctiondelaposition
ducaractreprcdentetparfoisenfonctiondescaractresdjanalyss.Lesalgorithmesde

204

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
labibliothquestandardqui manipulent lessquencesdecaractresdoivent doncstockerle
contextecourantlorsdelanalysedecessquences.Elleslefontgrceautypestate_typedela
classedestraitsdecescaractres.

Lexemplesuivantvouspermettradevrifierqueletypechar_typedelaclassededfinitiondestraits
pourletypecharestbienentenduletypecharluimme:
#include <iostream>
#include <typeinfo>
#include <string>
usingnamespacestd;
intmain(void)
{
//Rcuprelesinformationsdetypagedestraits:
consttype_info&ti_trait=
typeid(char_traits<char>::char_type);
//Rcuprelesinformationsdetypagedirectement:
consttype_info&ti_char=typeid(char);
//Comparelestypes:
cout << "Lenomdutypecaractredestraitsest:" <<
ti_trait.name() << endl;
cout << "Lenomdutypecharest:" <<
ti_char.name() << endl;
if(ti_trait==ti_char)
cout << "Lesdeuxtypessontidentiques."
<< endl;
else
cout << "Cenestpaslemmetype." << endl;
return0;
}

Laclassechar_traitsdfinitgalementuncertainnombredemthodestravaillantsurlestypesde
caractresetpermettantderaliserlesoprationsdebasesurcescaractres.Cesmthodespermettent
essentiellementdecomparer,decopier,dedplaceretderechercherdescaractresdansdessquences
decaractres,entenantcomptedetouteslescaractristiquesdecescaractres.Ellecontientgalement
ladfinitiondelavaleurspcialeutilisedanslessquencesdecaractrespourmarquerlesfindeflux
( EOF ,abrviationdelanglaisEndOfFile).
Parexemple,leprogrammesuivantpermetdafficherlavaleurutilisepourspcifierunefindefichier
dansunesquencedecaractresdetypewchar_t:
#include <iostream>
#include <string>
usingnamespacestd;
intmain(void)
{
char_traits<wchar_t>::int_typewchar_eof=
char_traits<wchar_t>::eof();
cout << "Lavaleurdefindefichierpourwchar_test:"
<< wchar_eof << endl;

205

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
return0;
}

Lesautresmthodesdelaclassededfinitiondestraitsdescaractres,ainsiquelesclassesded
finitiondestraitsdesautretypes,neserontpasdcritesplusendtailici.Ellessontessentiellement
utilisesauseindesalgorithmesdelabibliothquestandardetnontdoncquunintrtlimitpour
lesprogrammeurs,maisilestimportantdesavoirquellesexistent.

13.4.Abstractiondespointeurs:lesitrateurs
Labibliothquestandarddfinituncertainnombredestructuresdedonnesvolues,quipermettent
destockeretdemanipulerlesobjetsutilisateurdemanireoptimale,vitantainsiauprogrammeur
davoirrinventerlaroue. Onappellecesstructuresdedonnesdesconteneurs. Cesconteneurs
peuventtremanipulsautraversdefonctionsspciales,selonungrandnombredalgorithmespos
siblesdontlabibliothquedisposeenstandard.Lensembledesfonctionnalitsfourniesparlabiblio
thquepermetdesubveniraubesoindesprogrammeursdanslamajoritdescas.Nousdtailleronsla
notiondeconteneuretlesalgorithmesdisponiblesplusloindanscedocument.
Lamaniredaccderauxdonnesdesconteneursdpendbienentendudeleurnatureetdeleurstruc
ture.Celasignifiequenthorie,ilestncessairedespcialiserlesfonctionspermettantdappliquer
lesalgorithmespourchaquetypedeconteneurexistant.Cettetechniquenestnipratique,niexten
sible,puisquelesalgorithmesfournisparlabibliothquenepourraientdanscecaspastravaillersur
desconteneurscritsparleprogrammeur.Cestpourcetteraisonquelabibliothquestandardutilise
uneautretechniquepouraccderauxdonnesdesconteneurs.Cettetechniqueestbasesurlanotion
ditrateur.

13.4.1.Notionsdebaseetdfinition
Unitrateurnestriendautrequunobjetpermettantdaccdertouslesobjetsdunconteneurdonn,
souventsquentiellement,selonuneinterfacestandardise.Ladnominationditrateurprovientdonc
dufaitquelesitrateurspermettentditrersurlesobjetsdunconteneur,cestdiredenparcourir
lecontenuenpassantpartoussesobjets.
Commelesitrateurssontdesobjetspermettantdaccderdautresobjets,ilsnereprsententpas
euxmmescesobjets,maispluttlemoyendelesatteindre.Ilssontdonccomparablesauxpointeurs,
dont ilsont exactement lammesmantique. Enfait, lesconcepteursdelabibliothquestandard
sesontbasssurcettepropritpourdfinirlinterfacedesitrateurs, quisontdoncuneextension
*i ou
delanotiondepointeur. Parexemple, ilestpossibledcriredesexpressionstellesque
++i avecunitrateur i.Touslesalgorithmesdelabibliothque,quitravaillentnormalementsur
desitrateurs,sontdoncsusceptiblesdefonctionneravecdespointeursclassiques.
Bienentendu,pourlaplupartdesconteneurs,lesitrateursnesontpasdesimplespointeurs,maisdes
objetsquisecomportentcommedespointeursetquisontspcifiqueschaqueconteneur.Ainsi,les
algorithmessontcritsdemanireuniforme,etcesontlesconteneursquifournissentlesitrateurs
quileursontapproprisafindepermettrelaccsleursdonnes.
Ilnyaquetroismaniresdobtenirunitrateur.Lesitrateursquisonteffectivementdespointeurs
peuventtreobtenusnaturellementenprenantladressedellmentauquelilsdonnentaccs.Les
pointeursnedoiventtreutilissentantquitrateursquepouraccderauxdonnesduntableau,car
lasmantiquedelarithmtiquedespointeurssupposequeleslmentsrfrencssuccessivementpar
unpointeursontstocksendesemplacementscontigusdelammoire.Pourlesitrateursdeconte

206

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
neursenrevanche,ilfautimprativementutiliserdesmthodesspcifiquesduconteneurpourobtenir
desitrateurs.Laplupartdesconteneursfournissentunemthodepourobtenirunitrateurinitial,qui
rfrencelepremierlmentduconteneur,etunemthodepourobtenirlavaleurdelitrateurlorsque
leparcoursduconteneurestachev.Enfin,certainsalgorithmesetcertainesmthodesdesconteneurs
peuventretournerunitrateurlissudeleurtraitement.
Quelle que soit la manire dobtenir les itrateurs, leur validit est soumise des limites.
Premirement, ils deviennent obligatoirement invalides ds lors que le conteneur auquel ils
permettentdaccderestdtruit.Deplus,lesconteneursgrentleurstructurededonnesdemanire
dynamique,etsontsusceptiblesdelarorganiserdsquonlesmanipule.Onveilleradoncneplus
utiliserlesitrateursdunconteneurdsquunemthodepermettantdelemodifierauratappele.
Nepasrespectercettergleconduirait, danslemeilleurdescas, nepasparcourircompltement
lensembledesobjetsduconteneur,etdanslepiredescas,planterimmdiatementleprogramme.

13.4.2.Classificationdesitrateurs
Labibliothquedfinitplusieurscatgoriesditrateursquicontiennentdesitrateursplusoumoins
puissants. Lecomportement desitrateurslespluspuissantsserapprochebeaucoupdespointeurs
classiques, et quasiment touteslesoprationsapplicablesauxpointeurspeuvent ltrecesitra
teurs.Enrevanche,lesitrateursdesclassesplusrestrictivesnedfinissentquunsousensembledes
oprationsquelespointeurssupportent,etnepeuventdonctreutilissquedanslecadredecejeu
doprationsrduit.
Lesalgorithmesdelabibliothquenutilisentquelesitrateursdesclasseslesplusfaiblespermettant
deraliserleurtravail.Ilssimposentcesrestrictionsafindegarantirleurutilisationcorrectemme
aveclesitrateurslesplussimples.Bienentendu,commelespointeursdisposentdetouteslesfonc
tionnalitsdfiniesparlesitrateurs,mmelespluspuissants,lesalgorithmesstandardsfonctionnent
galementavecdespointeurs.Autrementdit,labibliothquestandardestcritedefaonnutiliser
quunepartiedesoprationsapplicablesauxpointeurs,afindegarantirquecequifonctionneavecdes
itrateursfonctionneavecdespointeurs.
Lesitrateursdechaquecatgoriepossdenttouteslespropritsdesitrateursdescatgoriesinf
rieures.Ilexistedoncunehirarchiedanslaclassificationdesitrateurs.Lescatgoriesdfiniespar
labibliothquestandardsontlessuivantes:

lesitrateursdelacatgorieOutputsontutilisspoureffectuerdesaffectationsdevaleursaux
donnesquilsrfrencent.Cesitrateursnepeuventdonctredrfrencsparloprateur*que
danslecadreduneaffectation.IlestimpossibledelirelavaleurdunitrateurdetypeOutput,et
onnedoitcriredanslavaleurquilsrfrencentquunefoisauplus.Lesalgorithmesquiutilisent
cesitrateursdoiventdoncimprativementnefairequuneseulepassesurlesdonnesitres;

lesitrateursdelacatgorieInput
sontsimilairesauxitrateursdetypeOutput,
ceciprs
quilsnepeuventtredrfrencsquepourlireunevaleur.Contrairementauxitrateursdetype
Output, ilestpossibledecomparerdeuxitrateurs. Cependant, lefaitquedeuxitrateurssoient
gauxnesignifieaucunementqueleurssuccesseursleserontencore.Lesalgorithmesquiutilisent
lesitrateursdetypeInputnepeuventdoncfaireaucunehypothsesurlordredeparcoursutilis
parlitrateur.Cesontdoncncessairementdesalgorithmesenunepasse;

lesitrateursdelacatgorieForwardpossdenttouteslesfonctionnalitsdesitrateursdetype
Input et detypeOutput. Commeceuxci, ilsnepeuvent passerquedunevaleurlasuivante,
etjamaisreculerourevenirunevaleurdjitre. Lesalgorithmesquiutilisentdesitrateurs
decettecatgoriesimposentdoncdeneparcourirlesdonnesdesconteneursquedansunseul
sens.Cependant,larestrictionimposesurlgalitdesoprateursdetypeInputestleve,cequi
signifiequeplusieursparcourssuccessifsseferontdanslemmeordre.Lesalgorithmespeuvent

207

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
effectuerplusieursparcours,parexempleencopiantlavaleurinitialedelitrateuretenparcourant
leconteneurplusieursfoisavecchaquecopie;

lesitrateursdelacatgorieBidirectionnaldisposentdetouteslesfonctionnalitsdesitrateurs
detypeForward, maislventlarestrictionsurlesensdeparcours.
Cesitrateurspeuventdonc
revenirsurlesdonnesdjitres,etlesalgorithmesquilesutilisentpeuventdonctravailleren
plusieurspasses,danslesdeuxdirections;

enfin,lesitrateursdelacatgorieRandomAccesssontlespluspuissants.Ilsfournissenttoutes
lesfonctionnalitsdesitrateursdetypeBidirectionnal,pluslapossibilitdaccderauxlments
desconteneursparlintermdiairedunindexenuntempsconstant.Ilnyadoncplusdenotion
desensdeparcours,etlesdonnespeuventtreaccdescommelesdonnesduntableau.Ilest
galement possibledeffectuerlesoprationsclassiquesdelarithmtiquedespointeurssurces
itrateurs.

Touslesitrateursdelabibliothquestandarddriventdelaclassedebasesuivante:
template <classCategory,
classT,classDistance=ptrdiff_t,
classPointer=T*,classReference=T&>
structiterator
{
typedefT
value_type;
typedefDistance difference_type;
typedefPointer
pointer;
typedefReferencereference;
typedefCategory iterator_category;
};

Cetteclasseestdclaredanslentte iterator.
Cetteclassedfinitlestypesdebasedesitrateurs,savoir:letypedesvaleursrfrences,letype
deladiffrenceentredeuxitrateursdanslescalculsdarithmtiquedespointeurs,letypedespoin
teursdesvaleursrfrencesparlitrateur,letypedesrfrencespourcesvaleursetlacatgoriede
litrateur.Cederniertypedoittrelunedesclassessuivantes,galementdfiniesparlabibliothque
standard:

input_iterator_tag,pourlesitrateursdelacatgoriedesitrateursdetypeInput;

output_iterator_tag,pourlesitrateursdelacatgoriedesitrateursdetypeOutput;

forward_iterator_tag,pourlesitrateursdelacatgoriedesitrateursdetypeForward;

bidirectionnal_iterator_tag,pourlesitrateursdelacatgoriedesitrateursbidirectionnels;

random_access_iterator_tag,pourlesitrateursdelacatgoriedesitrateursaccscomplet.

Notezqueletypepardfaut pourladiffrenceentredeuxpointeursest
letypeptrdiff_t, qui est
utilisclassiquement pourlespointeursnormaux. Demme, letypepointeuret letyperfrence
correspondentrespectivement,pardfaut,auxtypesT*etT&.Pourlesitrateurspourlesquelsces
typesnontpasdesens,letypeutilisestvoid,cequipermetdeprovoqueruneerreurdecompilation
sioncherchelesutiliser.
Cestypessontutilissparlesitrateursnativement,cependant,ilsnelesontgnralementpaspar
lesalgorithmes.Eneffet,ceuxcisontsusceptiblesdtreappelesavecdespointeursnormaux,etles
pointeursnedfinissentpastouscestypes.Cestpourcetteraisonquuneclassedetraitsatdfinie

208

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
pourlesitrateursparlabibliothquestandard.Cetteclasseestdclarecommesuitdanslentte
iterator :
template <classIterator>
structiterator_traits
{
typedefIterator::value_type
value_type;
typedefIterator::difference_type difference_type;
typedefIterator::pointer
pointer;
typedefIterator::reference
reference;
typedefIterator::iterator_categoryiterator_category;
};

Laclassedestraitspermetdoncdobtenirdemanireindpendantedelanaturedelitrateurlavaleur
destypesfondamentauxdelitrateur.Commecestypesnexistentpaspourlespointeursclassiques,
cetteclasseestspcialisedelamaniresuivante:
template <classT >
structiterator_traits<T* >
{
typedefT
value_type;
typedefptrdiff_tdifference_type;
typedefT
*pointer;
typedefT
&reference;
typedefrandom_access_iterator_tagiterator_category;
};

Ainsi,letypeiterator_traits<itrateur>::difference_typerenverratoujoursletypepermettantdesto
ckerladiffrenceentredeuxitrateurs,queceuxcisoientdesitrateursoudespointeursnormaux.
Pourcomprendrelimportancedestraitsdesitrateurs,prenonslexemplededeuxfonctionsfournies
parlabibliothquestandardpermettantdavancerunitrateurduncertainnombredtapes,etdecal
culerladiffrenceentredeuxitrateurs.Ilsagitrespectivementdesfonctionsadvance et distance.
Cesfonctionsdevantpouvoirtravailleravecnimportequelitrateur,etnimportequeltypededonne
pourexprimerladiffrenceentredeuxitrateurs,ellesutilisentlaclassedestraits.Ellessontdclares
delamaniresuivantedanslentte iterator :
template <classInputIterator,classDistance
>
voidadvance(InputIterator&i,Distancen);
template <classInputIterator>
iterator_traits<InputIterator>::difference_type
distance(InputIteratorfirst,InputIteratorlast);

Notezqueletypederetourdelafonction distance estIterator::difference_typepourlesitrateurs


normaux,etptrdiff_tpourlespointeurs.
Note:CesdeuxmthodesnesontpastrsefficacesaveclesitrateursdetypeForward,car
ellesdoiventparcourirlesvaleursdecesitrateursuneune.Cependant,ellessontspcialises
pourlesitrateursdetypeplusvolus(enparticulierlesitrateursaccscomplet),etsontdonc
plusefficacespoureux.Ellespermettentdoncdemanipulerlesitrateursdemanireuniforme,
sanspourautantcompromettrelesperformances.

209

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard

13.4.3.Itrateursadaptateurs
Lesitrateurssontunenotionextrmementutilisedanstoutelabibliothquestandard,
carilsre
groupenttouteslesfonctionnalitspermettantdeffectueruntraitementsquentieldesdonnes.Ce
pendant, ilnexistepastoujoursditrateurpourlessourcesdedonnesquelonmanipule.
Labi
bliothquestandardfournitdonccequelonappelledesitrateursadaptateurs,
quipermettentde
manipulercesstructuresdedonnesenutilisantlanotionditrateurmmesicesstructuresnegrent
pasellesmmeslanotionditrateur.

13.4.3.1.Adaptateurspourlesfluxdentre/sortiestandards
Lesfluxdentre/sortiestandardsdelabibliothquesontnormalementutilissaveclesoprations
>>et <<,respectivementpourrecevoiretpourenvoyerdesdonnes.Ilnexistepasditrateur
detypeInputetdetypeOutputpermettantdelireetdcriresurcesflux.Labibliothquedfinitdonc
desadaptateurspermettantdeconstruirecesitrateurs.
Litrateuradaptateurpourlesfluxdentreestimplmentparlaclasse template istream_iterator.
Cetadaptateurestdclarcommesuitdanslentte iterator :
template <classT,classcharT,classtraits=char_traits
<charT>,
classDistance=ptrdiff_t
>
classistream_iterator:
publiciterator<input_iterator_tag,T,Distance,
constT*,constT& >
{
public:
typedefcharT char_type;
typedeftraitstrait_type;
typedefbasic_istream<char,traits> istream_type;
istream_iterator();
istream_iterator(istream_iterator&flux);
istream_iterator(constistream_iterator
<T,charT,traits,
Distance> &flux);
~istream_iterator();
constT&operator*()const;
constT*operator >()const;
istream_iterator<T,charT,traits,Distance
> &operator++();
istream_iterator<T,charT,traits,Distance
> operator++(int);
};

Lesoprateursdgalitetdingalitsontgalementdfinispourcetitrateur.
Commevouspouvezleconstaterdaprscettedclaration,ilestpossibledeconstruireunitrateur
surunfluxdentrepermettantdelirelesdonnesdecefluxuneune.Silnyaplusdedonnes
liresurceflux,litrateurprendlavaleurdelitrateurdefindefichierpourleflux.Cettevaleurest
cellequiestattribuetoutnouvelitrateurconstruitsansfluxdentre.Lexemplesuivantprsente
commentfairelasommedeplusieursnombreslussurlefluxdentre,etdelafficherlorsquilnya
plusdedonneslire.
Exemple132.Itrateursdefluxdentre
#include <iostream>
#include <iterator>
usingnamespacestd;

210

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
intmain(void)
{
doublesomme=0;
istream_iterator<double,char> is(cin);
while(is!=istream_iterator
<double,char>())
{
somme=somme+*is;
++is;
}
cout << "Lasommedesvaleurslueest:"
<<
somme << endl;
return0;
}

Vouspourrezessayerceprogrammeentapantplusieursnombressuccessivementpuisenenvoyant
uncaractredefindefichieraveclacombinaisondetouches CTRL+Z .Cecaractreprovoquerala
sortiedelaboucle while etafficheralersultat.
Litrateuradaptateurpourlesfluxdesortiefonctionnedemanireencoreplussimple,carilnya
pasfairedetestsurlafindefichier.Ilestdclarcommesuitdanslentteiterator :
template <classT,classcharT=char,classtraits=char_traits<charT>>
classostream_iterator:
publiciterator<output_iterator_tag,void,void,void,void
>
{
public:
typedefcharT char_type;
typedeftraitstrait_type;
typedefbasic_ostream<charT,traits> ostream_type;
ostream_iterator(ostream_type&flux);
ostream_iterator(ostream_type&flux,constcharT*separateur);
ostream_iterator(constostream_iterator
<T,charT,traits> &flux);
~ostream_iterator();
ostream_iterator<T,charT,traits> &operator=(constT&valeur);
ostream_iterator<T,charT,traits> &operator*();
ostream_iterator<T,charT,traits> &operator++();
ostream_iterator<T,charT,traits> &operator++(int);
};

CetitrateurestdetypeOutput,etnepeutdonctredrfrencquedanslebutdefaireunecri
turedanslobjetainsiobtenu.Cedrfrencementretourneenfaitlitrateurluimme,sibienque
lcritureprovoquelappeldeloprateurdaffectationdelitrateur. Cetoprateurenvoiesimple
mentlesdonnessurlefluxdesortiequelitrateurprendenchargeetrenvoiesaproprevaleurafin
deraliserunenouvellecriture.Notezquelesoprateursdincrmentationexistentgalement,mais
nefontstrictementrien.Ilsnesontlquepourpermettredutilisercesitrateurscommedesimples
pointeurs.
Litrateurostream_iteratorpeutenvoyersurlefluxdesortieuntexteintercalaireentrechaquedonne
quonycrit.Cetextepeutservirinsrerdessparateursentrelesdonnes.Cettefonctionnalitpeut
savrertrspratiquepourlcriturededonnesformates.Letexteinsrerautomatiquementdoit
trepassentantquedeuximeargumentduconstructeurdelitrateur.

211

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
Exemple133.Itrateurdefluxdesortie
#include <iostream>
#include <iterator>
usingnamespacestd;
constchar*texte[6]={
"Bonjour","tout","le","monde","!",NULL
};
intmain(void)
{
ostream_iterator<constchar*,char> os(cout,"");
inti=0;
while(texte[i]!=NULL)
{
*os=texte[i]; //Ledrfrencementestfacultatif.
++os;
//Cetteligneestfacultative.
++i;
}
cout << endl;
return0;
}

Ilexistegalementdesadaptateurspourlestamponsdefluxdentre/sortiebasic_streambuf.
Le
premieradaptateurestimplmentparlaclasse template istreambuf_iterator.Ilpermetdelireles
donnesprovenantduntampondefluxbasic_streambufaussisimplementquenmanipulantunpoin
teuretenlisantlavaleurdelobjetpoint.Ledeuximeadaptateur,ostreambuf_iterator,permetquant
luidcriredansuntamponenaffectantunenouvellevaleurlobjetrfrencparlitrateur.Ces
adaptateursfonctionnentdoncexactementdelammemanirequelesitrateurspourlesfluxdentre
/sortieformats.Enparticulier,lavaleurdefindefichierqueprendlitrateurdentrepeuttrer
cuprelaideduconstructeurpardfautdelaclasseistreambuf_iterator,instanciepourletypede
tamponutilis.
Note:Loprateurdedincrmentationsuffixdesitrateursistreambuf_iteratorauntypede
retourparticulierqui permetdereprsenterlavaleurprcdentedelitrateuravant incrmen
tation.Lesobjetsdecetypesonttoujoursdrfrenableslaidedeloprateur *.Laraison
decetteparticularitestquelecontenudutamponpeuttremodifiaprslappeldeloprateur
operator++(int) ,maislanciennevaleurdecetitrateurdoittoujourspermettredaccder
lobjetquilrfrenait.Lavaleurretourneparlitrateurcontientdoncunesauvegardedecetob
jetetpeutsevoirappliquerloprateurdedrfrencement* parlappelantafindenrcuprer
lavaleur.
LanotiondetampondefluxseraprsenteendtaildanslaSection15.2.

13.4.3.2.Adaptateurspourlinsertiondlmentsdanslesconteneurs
Lesitrateursfournisparlesconteneurspermettentdenparcourirlecontenuetdobtenirunerf
rencesurchacundeleurslments.Cecomportementesttoutfaitclassiqueetconstituemmeune
desbasesdelanotionditrateur.Toutefois,linsertiondenouveauxlmentsdansunconteneurne
peutsefairequeparlintermdiairedesmthodesspcifiquesauxconteneurs.Labibliothquestan
dardC++dfinitdoncdesadaptateurspourdesitrateursditsdinsertion, quipermettentdinsrer

212

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
deslmentsdansdesconteneursparunsimpledrfrencementetunecriture.Grcecesadapta
teurs,linsertiondeslmentsdanslesconteneurspeuttreralisedemanireuniforme,delamme
manirequoncriraitdansuntableauquiseredimensionneraitautomatiquement,chaquecriture.
Ilestpossibledinsrerlesnouveauxlmentsenplusieursendroitsdanslesconteneurs.Ainsi,les
lmentspeuventtreplacsaudbutduconteneur,safin,ouaprsunlmentdonn.Bienentendu,
cesnotionsnont desensquepourlesconteneursqui nesont pasordonns, puisquedanslecas
contraire,lapositiondellmentinsrestdtermineparleconteneurluimme.
Laclasse template back_insert_iteratorestlaclassedeladaptateurdinsertionenfindeconteneur.
Elleestdclarecommesuitdanslentte iterator :
template <classContainer>
classback_insert_iterator:
publiciterator<output_iterator_tag,void,void,void,void
>
{
public:
typedefContainercontainer_type;
explicitback_insert_iterator(Container&conteneur);
back_insert_iterator<Container> &
operator=(consttypenameContainer::value_type&valeur);
back_insert_iterator<Container> &operator*();
back_insert_iterator<Container> &operator++();
back_insert_iterator<Container> operator++(int);
};

Commevouspouvezleconstater, lesobjetsdesinstancescetteclassepeuventtreutilisscomme
desitrateursdetypeOutput. Loprateurdedrfrencement *renvoielitrateurluimme, si
bienquelesaffectationssurlesitrateursdrfrencssonttraitesparloprateur operator=de
litrateurluimme. Cestdonccetoprateurquiajoutellmentaffecterlafinduconteneur
auquellitrateurpermetdaccder,enutilisantlamthode push_back decedernier.
Demme,laclasse template front_insert_iteratordeladaptateurdinsertionenttedeconteneur
estdclarecommesuitdanslentte iterator :
template <classContainer>
classfront_insert_iterator:
publiciterator<output_iterator_tag,void,void,void,void
>
{
public:
typedefContainercontainer_type;
explicitfront_insert_iterator(Container&conteneur);
front_insert_iterator<Container> &
operator=(consttypenameContainer::value_type&valeur);
front_insert_iterator<Container> &operator*();
front_insert_iterator<Container> &operator++();
front_insert_iterator<Container> operator++(int);
};

Sonfonctionnementestidentiqueceluideback_insert_iterator,ceciprsquileffectuelesinser
tionsdeslmentsaudbutduconteneur,parlintermdiairedesamthodepush_front.
Enfin,laclasse template deladaptateurditrateurdinsertionunepositiondonneestdclare
commesuit:
template <classContainer>
classinsert_iterator:
publiciterator<output_iterator_tag,void,void,void,void
>

213

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
{
public:
typedefContainercontainer_type;
insert_iterator(Container&conteneur,
typenameContainer::iteratorposition);
insert_iterator<Container> &
operator=(consttypenameContainer::value_type&valeur);
insert_iterator<Container> &operator*();
insert_iterator<Container> &operator++();
insert_iterator<Container> operator++(int);
};

Leconstructeur decetteclasseprendenparamtre,
enplusduconteneur sur lequel litrateur
dinsertiondoit travailler, unitrateur spcifiant lapositionlaquelleleslmentsdoivent
tre
insrs.Leslmentssontinsrsjusteavantllmentrfrencparlitrateurfournienparamtre.
Deplus,ilssontinsrssquentiellement,lesunsaprslesautres,dansleurordredaffectationvia
litrateur.
LabibliothquestandardC++fournit troisfonctions template qui permettent dobtenirlestrois
typesditrateurdinsertionpourchaqueconteneur. Cesfonctionssontdclarescommesuitdans
lentte iterator :
template <classContainer>
back_insert_iterator<Container>
back_inserter(Container&conteneur);
template <classContainer>
front_insert_iterator<Container>
front_inserter(Container&conteneur);
template <classContainer,classIterator>
insert_iterator<Container>
inserter(Container&conteneur,Iteratorposition);

Leprogrammesuivantutiliseunitrateurdinsertionpourremplirunelistedlment,
afficherlecontenu.

avantden

Exemple134.Itrateurdinsertion
#include <iostream>
#include <list>
#include <iterator>
usingnamespacestd;
//Dfinitletypelistedentier:
typedeflist<int> li_t;
intmain()
{
//Creuneliste:
li_tlst;
//Insredeuxlmentsdanslalistedelamanireclassique:
lst.push_back(1);
lst.push_back(10);

214

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
//Rcupreunitrateurrfrenantlepremierlment:
li_t::iteratorit=lst.begin();
//Passeaudeuximelment:
++it;
//Construitunitrateurdinsertionpourinsrerdenouveaux
//lmentsavantledeuximelmentdelaliste:
insert_iterator<li_t> ins_it=inserter(lst,it);
//Insreleslmentsaveccetitrateur:
for(inti=2;i
< 10;++i)
{
*ins_it=i;
++ins_it;
}
//Affichelecontenudelaliste:
it=lst.begin();
while(it!=lst.end())
{
cout << *it << endl;
++it;
}
return0;
}

LamaniredutiliserleconteneurdetypelistseradcriteendtaildansleChapitre17.

13.4.3.3.Itrateurinversepourlesitrateursbidirectionnels
Lesitrateursbidirectionnelsetlesitrateursaccsalatoirepeuventtreparcourusdanslesdeux
sens.Pourcesitrateurs,ilestdoncpossiblededfinirunitrateurassocidontlesensdeparcours
estinvers.Lepremierlmentdecetitrateurestdoncledernierlmentdelitrateurassoci,et
inversement.
LabibliothquestandardC++dfinitunadaptateurpermettantdobtenirunitrateurinversefacile
mentdanslentte iterator.Ilsagitdelaclasse template reverse_iterator:
template <classIterator>
classreverse_iterator:
publiciterator<
iterator_traits<Iterator>::iterator_category,
iterator_traits<Iterator>::value_type,
iterator_traits<Iterator>::difference_type,
iterator_traits<Iterator>::pointer,
iterator_traits<Iterator>::reference>
{
public:
typedefIteratoriterator_type;
reverse_iterator();
explicitreverse_iterator(Iteratoriterateur);
Iteratorbase()const;
Referenceoperator*()const;
Pointeroperator>()const;
reverse_iterator&operator++();
reverse_iteratoroperator++(int);
reverse_iterator&operator();
reverse_iteratoroperator(int);
reverse_iteratoroperator+(Distancedelta)const;

215

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
reverse_iterator&operator+=(Distancedelta);
reverse_iteratoroperator(Distancedelta)const;
reverse_iterator&operator=(Distancedelta);
Referenceoperator[](Distancedelta)const;
};

Lesoprateursdecomparaisonclassiqueset darithmtiquedespointeursexternes operator+ et


operator sontgalementdfinisdanscetentte.
Leconstructeurdecetadaptateurprendenparamtrelitrateurassocidanslesensinverseduquel
leparcoursdoitsefaire.Litrateurinversepointeraalorsautomatiquementsurllmentprcdent
llmentpointparlitrateurpassenparamtre. Ainsi, sioninitialiselitrateurinverseavecla
valeurdefindelitrateurdirect,ilrfrenceraledernierlmentquelitrateurdirectauraitrfrenc
avant dobtenirsavaleurfinaledansunparcoursdeslmentsduconteneur. Lavaleurdefinde
litrateurinversepeuttreobtenueenconstruisantunitrateurinversepartirdelavaleurdedbut
delitrateurdirect.
Note:Notezqueleprincipespcifiantqueladressesuivantcelledudernierlmentduntableau
doittoujourstreuneadressevalideestgalementenvigueurpourlesitrateurs.Lavaleurde
findunitrateurest assimilablecetteadresse, pointant surlemplacement suivant ledernier
lmentduntableau,etnestpasplusdrfrenable,carellesetrouveendehorsdutableau.
Cependant,ellepeuttreutilisedanslescalculsdarithmtiquedespointeurs,etcestexacte
mentcequefaitladaptateurreverse_iterator.

Lamthode base permetdercuprerlavaleurdelitrateurdirectassocilitrateurinverse.On


prendragardequelitrateurrenvoyparcettemthodenerfrencepaslemmelmentquecelui
rfrencparlitrateurinverse.Eneffet,llmentrfrencesttoujoursllmentsuivantllment
rfrencparlitrateurinverse,enraisondelamaniredontcetitrateurestinitialis.Parexemple,
litrateurinverserfrenceledernierlment duconteneurlorsquil vient dtreintialisavecla
valeurdefindelitrateurdirecte,valeurquireprsenteledernierlmentpass.Demme,lorsque
litrateurinverseapourvaleursavaleurdefinditration(cequireprsentellmentprcdentle
premierlmentduconteneurenquelquesorte), litrateurdirectrfrencelepremierlmentdu
conteneur.
Enfait, lesitrateursinversessontutilisseninterneparlesconteneurspourfournirdesitrateurs
permettantdeparcourirleursdonnesdanslesensinverse.Leprogrammeurnauradoncgnralement
pasbesoindeconstruiredesitrateursinversesluimme,ilutiliserapluttlesitrateursfournispar
lesconteneurs.
Exemple135.Utilisationdunitrateurinverse
#include <iostream>
#include <list>
#include <iterator>
usingnamespacestd;
//Dfinitletypelistedentier:
typedeflist<int> li_t;
intmain(void)
{
//Creunenouvelleliste:
li_tli;

216

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
//Remplitlaliste:
for(inti=0;i
< 10;++i)
li.push_back(i);
//Affichelecontenudelalistelenvers:
li_t::reverse_iteratorrev_it=li.rbegin();
while(rev_it!=li.rend())
{
cout << *rev_it << endl;
++rev_it;
}
return0;
}

13.5.Abstractiondesfonctions:lesfoncteurs
Laplupart desalgorithmesdelabibliothquestandard, ainsi quequelquesmthodesdesclasses
quellefournit, donnentlapossibilitlutilisateurdappliquerunefonctionauxdonnesmanipu
les.Cesfonctionspeuventtreutilisespourdiffrentestches,commepourcomparerdeuxobjets
parexemple,outoutsimplementpourenmodifierlavaleur.
Cependant, labibliothquestandardnutilisepascesfonctionsdirectement, maisaplutt recours
uneabstractiondesfonctions: lesfoncteurs. Unfoncteurnest riendautrequunobjet dont la
classedfinitloprateurfonctionnel ().Lesfoncteursontlaparticularitdepouvoirtreutiliss
exactementcommedesfonctionspuisquilestpossibledeleurappliquerleuroprateurfonctionnel
selonunecrituresimilaireunappeldefonction.Cependant,ilssontunpeupluspuissantsquede
simplesfonctions,carilspermettentdetransporter,enplusducodedeloprateurfonctionnel,des
paramtresadditionnelsdansleursdonnesmembres.Lesfoncteursconstituentdoncunefonctionna
litextrmementpuissantequipeuttretrspratiqueendenombreuxendroits.Enfait,commeonle
verraplusloin,toutefonctionpeuttretransformeenfoncteur.Lesalgorithmesdelabibliothque
standardpeuventdoncgalementtreutilissavecdesfonctionsclassiquesmoyennantcettepetite
transformation.
Lesalgorithmesdelabibliothquestandardquiutilisentdesfoncteurssontdclarsavecunparamtre
template dontlavaleurseracelledufoncteurpermettantderaliserloprationappliquersurles
donnesencoursdetraitement. Auseindecesalgorithmes, lesfoncteurssont utilisscommede
simplesfonctions, et labibliothquestandardnefait doncpasdautrehypothsesurleurnature.
Cependant, il est ncessairedenedonnerquedesfoncteursenparamtresauxalgorithmesdela
bibliothquestandard,pasdesfonctions.Cestpourcetteraisonquelabibliothquestandarddfinit
uncertainnombredefoncteursstandardsafindefaciliterlatcheduprogrammeur.

13.5.1.Foncteursprdfinis
Labibliothquenutilise, danssesalgorithmes, quedesfoncteursqui neprennent quunoudeux
paramtres. Lesfoncteursquiprennentunparamtreetunseulsontditsunaires, alorsqueles
foncteursquiprennentdeuxparamtressontqualifisdebinaires.Afindefaciliterlacrationde
foncteursutilisablesavecsesalgorithmes,labibliothquestandarddfinitdeuxclassesdebasequi
pourlesfoncteursunairesetbinaires.Cesclassesdebasesontlessuivantes:
template <classArg,classResult>
structunary_function

217

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
{
typedefArg
argument_type;
typedefResultresult_type;
};
template <classArg1,classArg2,classResult>
structbinary_function
{
typedefArg1
first_argument_type;
typedefArg2
second_argument_type;
typedefResultresult_type;
};

Cesclassessontdfiniesdanslentte functional.
Labibliothquedfinitgalementuncertainnombredefoncteursstandardsquiencapsulentlesop
rateursdulangagedanscetentte.Cesfoncteurssontlessuivants:
template <classT >
structplus:binary_function
<T,T,T >
{
Toperator()(constT&operande1,constT&operande2)const;
};
template <classT >
structminus:binary_function
<T,T,T >
{
Toperator()(constT&operande1,constT&operande2)const;
};
template <classT >
structmultiplies:binary_function
<T,T,T >
{
Toperator()(constT&operande1,constT&operande2)const;
};
template <classT >
structdivides:binary_function
<T,T,T >
{
Toperator()(constT&operande1,constT&operande2)const;
};
template <classT >
structmodulus:binary_function
<T,T,T >
{
Toperator()(constT&operande1,constT&operande2)const;
};
template <classT >
structnegate:unary_function
<T,T >
{
Toperator()(constT&operande)const;
};
template <classT >
structequal_to:binary_function
<T,T,bool>
{
booloperator()(constT&operande1,constT&operande2)const;

218

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
};
template <classT >
structnot_equal_to:binary_function<T,T,bool>
{
booloperator()(constT&operande1,constT&operande2)const;
};
template <classT >
structgreater:binary_function
<T,T,bool>
{
booloperator()(constT&operande1,constT&operande2)const;
};
template <classT >
structless:binary_function
<T,T,bool>
{
booloperator()(constT&operande1,constT&operande2)const;
};
template <classT >
structgreater_equal:binary_function <T,T,bool>
{
booloperator()(constT&operande1,constT&operande2)const;
};
template <classT >
structless_equal:binary_function
<T,T,bool>
{
booloperator()(constT&operande1,constT&operande2)const;
};

Cesfoncteurspermettentdutiliserlesprincipauxoprateursdulangagecommedesfonctionsclas
siquesdanslesalgorithmesdelabibliothquestandard.
Exemple136.Utilisationdesfoncteursprdfinis
#include <iostream>
#include <functional>
usingnamespacestd;
//Fonctiontemplateprenantenparamtredeuxvaleurs
//etunfoncteur:
template <classT,classF >
Tapplique(Ti,Tj,Ffoncteur)
{
//Appliqueloprateurfonctionnelaufoncteur
//aveccommeargumentslesdeuxpremiersparamtres:
returnfoncteur(i,j);
}
intmain(void)
{
//Construitlefoncteurdesomme:
plus<int> foncteur_plus;
//Utilisecefoncteurpourfairefaireuneaddition

219

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
//lafonction"applique":
cout << applique(2,3,foncteur_plus)<< endl;
return0;
}

Danslexempleprcdent,lafonction templateappliqueprendentroisimeparamtreunfonc
teuret lutilisepourraliserloprationfaireaveclesdeuxpremiersparamtres. Cettefonction
nepeutthoriquementtreutilisequavecdesobjetsdisposantdunoprateurfonctionnel (),et
pasavecdesfonctionsnormales.Labibliothquestandardfournitdonclesadaptateurssuivants,qui
permettentdeconvertirrespectivementnimportequellefonctionunaireoubinaireenfoncteur:
template <classArg,classResult>
classpointer_to_unary_function:
publicunary_function<Arg,Result>
{
public:
explicitpointer_to_unary_function(Result(*fonction)(Arg));
Resultoperator()(Argargument1)const;
};
template <classArg1,Arg2,Result>
classpointer_to_binary_function:
publicbinary_function<Arg1,Arg2,Result>
{
public:
explicitpointer_to_binary_function(Result(*fonction)(Arg1,Arg2));
Resultoperator()(Arg1argument1,Arg2argument2)const;
};
template <classArg,classResult>
pointer_to_unary_function
<Arg,Result>
ptr_fun(Result(*fonction)(Arg));
template <classArg,classResult>
pointer_to_binary_function
<Arg1,Arg2,Result>
ptr_fun(Result(*fonction)(Arg1,Arg2));

Lesdeuxsurchargesdelafonction templateptr_funpermettentdefaciliterlaconstructiondun
foncteurunaireoubinairepartirdupointeurdunefonctiondummetype.
Exemple137.Adaptateursdefonctions
#include <iostream>
#include <functional>
usingnamespacestd;
template <classT,classF >
Tapplique(Ti,Tj,Ffoncteur)
{
returnfoncteur(i,j);
}
//Fonctionclassiqueeffectuantunemultiplication:
intmul(inti,intj)
{
returni*j;

220

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
}
intmain(void)
{
//Utiliseunadaptateurpourtransformerlepointeur
//surlafonctionmulenfoncteur:
cout << applique(2,3,ptr_fun(&mul))<< endl;
return0;
}

Note:EnralitlelangageC++estcapabledappelerunefonctiondirectementpartirdeson
adresse,sansdrfrencement.Depluslenomdunefonctionreprsentetoujourssontadresse,
etestdoncconvertiimplicitementparlecompilateurenpointeurdefonction.Parconsquent,il
esttoutfaitpossibledutiliserlafonction templateapplique avecuneautrefonctiondeux
paramtres,commedanslappelsuivant:
applique(2,3,mul);

Cependant,cettecritureprovoquelaconversionimplicitedelidentificateurmul enpointeurde
fonctionprenantdeuxentiersenparamtresetrenvoyantunentier,dunepart,etlappel dela
template
fonction mul parlintermdiairedesonpointeursansdrfrencementdanslafonction
applique dautrepart.Cettecritureestdoncaccepteparlecompilateurpartolrance,mais
nestpasrigoureusementexacte.

LabibliothquestandardC++dfinitgalementdesadaptateurspourlespointeursdemthodesnon
statiquesdeclasses. Cesadaptateursseconstruisent commelesadaptateursdefonctionsstatiques
classiques,ceciprsqueleurconstructeurprendunpointeurdemthodedeclasseetnonunpointeur
defonctionnormale.Ilssontdclarsdelamaniresuivantedanslenttefunctional :
template <classResult,classClass
>
classmem_fun_t:
publicunary_function<Class*,Result>
{
public:
explicitmem_fun_t(Result(Class::*methode)());
Resultoperator()(Class*pObjet);
};
template <classResult,classClass,classArg
>
classmem_fun1_t:
publicbinary_function<Class*,Arg,Result>
{
public:
explicitmem_fun1_t(Result(Class::*methode)(Arg));
Resultoperator()(Class*pObjet,Argargument);
};
template <classResult,classClass
>
classmem_fun_ref_t:
publicunary_function<Class,Result>
{
public:
explicitmem_fun_ref_t(Result(Class::*methode)());

221

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
Resultoperator()(Class&objet);
};
template <classResult,classClass,classArg
>
classmem_fun1_ref_t:
publicbinary_function<Class,Arg,Result>
{
public:
explicitmem_fun1_ref_t(Result(Class::*methode)(Arg));
Resultoperator()(Class&objet,Argargument);
};
template <classResult,classClass
>
mem_fun_t<Result,Class> mem_fun(Result(Class::*methode)());
template <classResult,classClass,classArg
>
mem_fun1_t<Result,Class> mem_fun(Result(Class::*methode)(Arg));
template <classResult,classClass
>
mem_fun_ref_t<Result,Class> mem_fun_ref(Result(Class::*methode)());
template <classResult,classClass,classArg
>
mem_fun1_ref_t<Result,Class>
mem_fun_ref(Result(Class::*methode)(Arg));

Commevouspouvezleconstaterdaprsleursdclarationslesoprateursfonctionnelsdecesadap
tateursprennentenpremierparamtresoitunpointeursurlobjetsurlequellefoncteurdoittravailler
(adaptateursmem_fun_tetmem_fun1_t),soitunerfrencesurcetobjet(adaptateursmem_fun_ref_t
etmem_fun1_ref_t).Lepremierparamtredecesfoncteursestdoncrservpourlobjetsurlequel
lamthodeencapsuledoittreappele.
Enfait,lalistedesadaptateursprsentecidessusnestpasexhaustive.Eneffet,chaqueadaptateur
prsentestdoubldunautreadaptateur,capabledeconvertirlesfonctionsmembres const.Ilexiste
donchuitadaptateursautotalpermettantdeconstruiredesfoncteurspartirdesfonctionsmembres
declasses.Pourdiminuercettecomplexit,labibliothquestandarddfinitplusieurssurchargespour
lesfonctions mem_fun et mem_fun_ref,quipermettentdeconstruiretouscesfoncteursplusfacile
ment,sansavoirsesoucierdelanaturedespointeursdefonctionmembreutiliss.Ilestfortement
recommanddelesutiliserpluttquedechercherconstruirecesobjetsmanuellement.

13.5.2.Prdicatsetfoncteursdoprateurslogiques
Lesfoncteursquipeuventtreutilissdansuneexpressionlogiqueconstituentuneclasseparticulire:
lesprdicats.Unprdicatestunfoncteurdontloprateurfonctionnelrenvoieunboolen.Lesprdi
catsontdoncunsenslogique,etcaractrisentunepropritquinepeuttrequevraieoufausse.
Labibliothquestandardfournit desprdicatsprdfinisqui effectuent lesoprationslogiques
desoprateurslogiquesdebasedulangage. Cesprdicatssont galement dclarsdanslentte
functional :
template <classT >
structlogical_and:
binary_function<T,T,bool>
{
booloperator()(constT&operande1,constT&operande2)const;

222

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
};
template <classT >
structlogical_or:
binary_function<T,T,bool>
{
booloperator()(constT&operande1,constT&operande2)const;
};

Cesfoncteursfonctionnentexactementcommelesfoncteursvusdanslasectionprcdente.
Labibliothquestandarddfinitaussideuxfoncteursparticuliers,quipermettentdeffectuerlanga
tiondunautreprdicat.Cesdeuxfoncteurstravaillentrespectivementsurlesprdicatsunairesetsur
lesprdicatsbinaires:
template <classPredicate>
classunary_negate:
publicunary_function<typenamePredicate::argument_type,bool
>
{
public:
explicitunary_negate(constPredicate&predicat);
booloperator()(constargument_type&argument)const;
};
template <classPredicate>
classbinary_negate:
publicbinary_function<typenamePredicate::first_argument_type,
typenamePredicate::second_argument_type,bool
>
{
public:
explicitbinary_negate(constPredicate&predicat);
booloperator()(constfirst_argument_type&argument1,
constsecond_argument_type&argument2)const;
};
template <classPredicate>
unary_negate<Predicate> not1(constPredicate&predicat);
template <classPredicate>
binary_negate<Predicate> not2(constPredicate&predicat);

Lesfonctions not1 et not2 serventfaciliterlaconstructiondunprdicatinversepourlesprdicats


unairesetbinaires.

13.5.3.Foncteursrducteurs
Nousavonsvuquelabibliothquestandardnetravaillaitquavecdesfoncteursprenantauplusdeux
arguments. Certainsalgorithmesnutilisantquedesfoncteursunaires, ilsnesontnormalementpas
capablesdetravailleraveclesfoncteursbinaires.Toutefois,siundesparamtresdunfoncteurbinaire
estfixunevaleurdonne,celuicidevientunaire,puisqueseulledeuximeparamtrepeutvarier.
Ilestdoncpossibledutiliserdesfoncteursbinairesmmeavecdesalgorithmesquinutilisentque
desfoncteursunaires,laconditiondefixerlundesparamtres.
Labibliothquestandarddfinitdesfoncteursspciauxquipermettentdetransformertoutfoncteur
binaireenfoncteurunairepartirdelavaleurdelundesparamtres.Cesfoncteurseffectuentune
oprationditederductioncarilsrduisentlenombredeparamtresdufoncteurbinaireun.Pour

223

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
cela,ilsdfinissentunoprateurfonctionnelunargument,quiappliqueloprateurfonctionneldu
foncteurbinairecetargumentetunevaleurfixequilsmmorisentendonnemembre.
Cesfoncteursrducteurssontdclars,commelesautresfoncteurs,danslentte fonctional :
template <classOperation>
classbinder1st:
publicunary_function<typenameOperation::second_argument_type,
typenameOperation::result_type
>
{
protected:
Operationop;
typenameOperation::first_argument_typevalue;
public:
binder1st(constOperation&foncteur,
consttypenameOperation::first_argument_type&valeur);
result_typeoperator()(constargument_type&variable)const;
};
template <classOperation>
classbinder2nd:
publicunary_function<typenameOperation::first_argument_type,
typenameOperation::result_type
>
{
protected:
Operationop;
typenameOperation::second_argument_typevalue;
public:
binder2nd(constOperation&foncteur,
consttypenameOperation::second_argument_type&valeur);
result_typeoperator()(constargument_type&variable)const;
};
template <classOperation,classT >
binder1st<Operation> bind1st(constOperation&foncteur,constT&valeur);
template <classOperation,classT >
binder2nd<Operation> bind2nd(constOperation&foncteur,constT&valeur);

Ilexistedeuxjeuxderducteurs, quipermettentderduirelesfoncteursbinairesenfixantrespec
tivementleurpremierouleurdeuximeparamtre. Lesrducteursquifigentlepremierparamtre
peuventtreconstruitslaidedelafonction templatebind1st, etceuxquifigentlavaleurdu
deuximeparamtrepeuventltrelaidedelafonction bind2nd.
Exemple138.Rductiondefoncteursbinaires
#include <iostream>
#include <functional>
usingnamespacestd;
//Fonctiontemplatepermettantdappliquerunevaleur
//unfoncteurunaire.Cettefonctionnepeutpas
//treutiliseavecunfoncteurbinaire.
template <classFoncteur>
typenameFoncteur::result_typeapplique(

224

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
Foncteurf,
typenameFoncteur::argument_typevaleur)
{
returnf(valeur);
}
intmain(void)
{
//Construitunfoncteurbinairedadditiondentiers:
plus<int> plus_binaire;
inti;
for(i=0;i < 10;++i)
{
//Rduitlefoncteurplus_binaireenfixantson
//premierparamtre35.Lefoncteurunaireobtenu
//estensuiteutilisaveclafonctionapplique:
cout << applique(bind1st(plus_binaire,35),i)<< endl;
}
return0;
}

13.6.Gestionpersonnalisedelammoire:les
allocateurs
Lunedesplusgrandesforcesdelabibliothquestandardestdedonnerauxprogrammeurslecontrle
totaldelagestiondelammoirepourleursobjets. Eneffet, lesconteneurspeuventtreamens
crerungrandnombredobjets,dontlecomportementpeuttretrsdiffrentselonleurtype.Si,dans
lamajoritdescas,lagestiondelammoireeffectueparlabibliothquestandardconvient,ilpeut
parfoistrencessairedeprendreenchargesoimmelesallocationsetleslibrationsdelammoire
pourcertainsobjets.
Labibliothquestandardutilisepourcelalanotiondallocateur. UnallocateurestuneclasseC++
disposantdemthodesstandardsquelesalgorithmesdelabibliothquepeuventappelerlorsquelles
dsirentalloueroulibrerdelammoire.Pourcela,lesconteneursdelabibliothquestandardC++
prennenttousunparamtre template reprsentantletypedesallocateursmmoirequilsdevront
utiliser. Bienentendu, labibliothquestandardfournit unallocateur par dfaut, et ceparamtre
template prendpardfautlavaleurdecetallocateur.
Ainsi, lesprogrammesquinedsirentpas
spcifierunallocateurspcifiquepourrontsimplementignorerceparamtretemplate.
Lesautresprogrammespourrontdfinirleurpropreallocateur.Cetallocateurdevravidemmentfour
nirtouteslesfonctionnalitsdelallocateurstandard, et satisfairequelquescontraintesparticu
lires.Linterfacedesallocateursestfournieparladclarationdelallocateurstandard,danslentte
memory :
template <classT >
classallocator
{
public:
typedefsize_t
size_type;
typedefptrdiff_tdifference_type;
typedefT
*pointer;
typedefconstT
*const_pointer;

225

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
typedefT
&reference;
typedefconstT
&const_reference;
typedefT
value_type;
template <classU >
structrebind
{
typedefallocator<U> other;
};
allocator()throw();
allocator(constallocator&)throw();
template <classU >
allocator(constallocator
<U> &)throw();
~allocator()throw();
pointeraddress(referenceobjet);
const_pointeraddress(const_referenceobjet)const;
pointerallocate(size_typenombre,
typenameallocator<void>::const_pointerindice);
voiddeallocate(pointeradresse,size_typenombre);
size_typemax_size()constthrow();
voidconstruct(pointeradresse,constT&valeur);
voiddestroy(pointeradresse);
};
//Spcialisationpourletypevoidpourliminerlesrfrences:
template <>
classallocator<void>
{
public:
typedefvoid
*pointer;
typedefconstvoid*const_pointer;
typedefvoid
value_type;
template <classU >
structrebind
{
typedefallocator<U> other;
};
};

Vousnoterezquecetallocateurestspcialispourletypevoid,
typedef nontpasdesenspourcetypededonne.

carcertainesmthodesetcertains

Lerledechacunedesmthodesdesallocateursesttrsclairetnappellepasbeaucoupdecommen
taires.Lesdeuxsurchargesdelamthode address permettentdobtenirladressedunobjetallou
parcetallocateurpartirdunerfrence.Lesmthodes allocate et deallocate permettentres
pectivementderaliseruneallocationdemmoireetlalibrationdubloccorrespondant.Lamthode
allocate prendenparamtrelenombredobjetsquidevronttrestocksdansleblocalloueret
unpointeurfournissantdesinformationspermettantdedterminerlemplacementolallocationdoit
sefairedeprfrence.Cedernierparamtrepeutnepastreprisencompteparlimplmentationde
labibliothquestandardquevousutilisezet,sillest,sonrlenestpasspcifi.Danstouslescas,
silnestpasnul,cepointeurdoittreunpointeursurunblocdjallouparcetallocateuretnon
encorelibr.Laplupartdesimplmentationschercherontallouerunblocadjacentceluifourni
enparamtre,maiscenestpastoujourslecas.Demme,notezquelenombredobjetsspcifila
mthode deallocate doitexactementtrelemmequeceluiutilispourlallocationdanslappel
correspondant allocate.Autrementdit,lallocateurnemmorisepasluimmelatailledesblocs
mmoirequilafourni.

226

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
allocate nest ni libr, ni rallou, ni
Note:Lepointeurpassenparamtrelamthode
rutilisparlallocateur.Ilnesagitdoncpasdunemodificationdelataillemmoiredublocfourni
enparamtre, et ceblocdevratoujourstrelibrindpendamment decelui qui seraallou.
Cepointeurnestutilisparlesimplmentationsquecommeunindicefourni lallocateurafin
doptimiserlesallocationsdeblocsdanslesalgorithmesetlesconteneursinternes.

Lamthode allocate peutlancerlexceptionbad_allocencasdemanquedemmoireousile


nombredobjetsspcifienparamtreest tropgros. Vouspourrezobtenirlenombremaximal
quelamthode allocate estcapabledacceptergrcelamthode max_size delallocateur.

Lesdeuxmthodes construct et destroy permettentrespectivementdeconstruireunnouvelob


jetetdendtruireunladresseindiqueenparamtre.Ellesdoiventtreutiliseslorsquondsire
appelerleconstructeurouledestructeurdunobjetstockdansunezonemmoirealloueparcetal
locateuretnonparlesoprateurs new et delete dulangage(rappelonsquecesoprateurseffectuent
cetravail automatiquement). Poureffectuerlaconstructiondunnouvel objet, construct utilise
loprateur new avecplacement,etpourledtruire, destroy appelledirectementledestructeurde
lobjet.
Note:Lesmthodes construct et destroy neffectuent paslallocationet lalibrationdela
mmoireellesmmes.Cesoprationsdoiventtreeffectuesaveclesmthodes allocate et
deallocate delallocateur.

Exemple139.Utilisationdelallocateurstandard
#include <iostream>
#include <memory>
usingnamespacestd;
classA
{
public:
A();
A(constA&);
~A();
};
A::A()
{
cout << "ConstructeurdeA" << endl;
}
A::A(constA&)
{
cout << "ConstructeurdecopiedeA" << endl;
}
A::~A()
{
cout << "DestructeurdeA"
}

<< endl;

intmain(void)

227

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
{
//ConstruituneinstancedelallocateurstandardpourlaclasseA:
allocator<A> A_alloc;
//AllouelespacencessairepourstockercinqinstancesdeA:
allocator<A>::pointerp=A_alloc.allocate(5);
//Construitcesinstancesetlesinitialise:
Ainit;
inti;
for(i=0;i <5;++i)
A_alloc.construct(p+i,init);
//Dtruitcesinstances:
for(i=0;i <5;++i)
A_alloc.destroy(p+i);
//Reconstruitces5instances:
for(i=0;i <5;++i)
A_alloc.construct(p+i,init);
//Destructionfinale:
for(i=0;i <5;++i)
A_alloc.destroy(p+i);
//Librelammoire:
A_alloc.deallocate(p,5);
return0;
}

Vousvoyezicilintrtquepeutavoirlesallocateursdelabibliothquestandard.
Lesalgorithmes
peuventcontrlerexplicitementlaconstructionetladestructiondesobjets,
etsurtoutlesdissocier
desoprationsdallocationet delibrationdelammoire. Ainsi, unalgorithmedevant effectuer
beaucoupdallocationsmmoirepourra,silledsire,effectuercesallocationsunebonnefoispour
toutesgrcelallocateurstandard,etneffectuerlesoprationsdeconstructionetdedestructiondes
objetsquelorsquecelaestncessaire.Enprocdantainsi,letempspassdanslesroutinesdegestion
delammoireestliminetlalgorithmeestdautantplusperformant. Inversement, unutilisateur
exprimentpourradfinirsonpropreallocateurmmoireadaptauxobjetsquil
voudrastocker
dansunconteneur. Enimposant auconteneurdelabibliothquestandarddutilisercet
allocateur
personnalis,ilobtiendradesperformancesoptimales.
Ladfinitiondunallocateurmaisonconsistesimplementimplmenteruneclasse template dispo
santdesmmesmthodesettypesqueceuxdfinisparlallocateurallocator.Toutefois,ilfautsavoir
quelabibliothqueimposedescontraintessurlasmantiquedecesmthodes:

228

touteslesinstancesdelaclasse template delallocateurpermettentdaccderlammemmoire.


Cesinstancessontdoncinterchangeablesetilestpossibledepasserdelunelautrelaidedela
structure template rebindetdeson typedef other.Notezquelefaitdencapsulerce typedef
dansunestructure template permetdesimulerladfinitionduntype template ;

touteslesinstancesdunallocateurduntypedonnpermettentgalementdaccderlamme
mmoire.Celasignifiequilnestpasncessairededisposerduneinstanceglobalepourchaque
allocateur,ilsuffitsimplementdecrerunobjetlocaldunedesinstancesdelaclasse template
delallocateurpouralloueret librerdelammoire. Notezici ladiffrenceaveclacontrainte
template instancies,
prcdente:cettecontrainteporteicisurlesobjetsinstancesdesclasses
alorsquelacontrainteprcdenteportaitsurlesinstancesellesmmesdelaclasse template de
lallocateur;

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard

touteslesmthodesdelallocateurdoiventsexcuterdansuntempsamorticonstant(celasignifie
queletempsdexcutiondecesmthodesestmajorparunebornesuprieurefixe,quinedpend
pasdunombredallocationdjeffectuesnidelatailledublocdemmoiredemand);

lesmthodes allocate et deallocate sontsusceptiblesdutiliserlesoprateurs new et delete


dulangage. Cenest pasuneobligation, maiscettecontraintesignifiequelesprogrammesqui
redfinissentcesdeuxoprateursdoiventtrecapabledesatisfairelesdemandesdelallocateur
standard;

lestypespointer, const_pointer, size_typeet difference_typedoivent tregauxrespectivement


auxtypesT*, constT*, size_tetptrdiff_t. Enfait, cettecontraintenestimposequepourles
allocateursdestinstreutilissparlesconteneursdelabibliothquestandard,maisilestplus
simpledelagnralisertouslescasdutilisation.

Pourterminercetourdhorizondesallocateurs,sachezquelabibliothquestandarddfinitgalement
untypeitrateurspcialpermettantdestockerdesobjetsdansunezonedemmoirenoninitialise.
Cet itrateur, nommraw_storage_iterator, est detypeOutput et nest utilisqueninterneparla
bibliothquestandard.Demme,labibliothquedfinitdesalgorithmespermettantdeffectuerdes
copiesbrutesdeblocsmmoireetdautresmanipulationssurlesblocsallousparlesallocateurs.Ces
algorithmessontgalementutilisseninterne,etneserontdoncpasdcritsplusendtailici.

13.7.Notiondecomplexitalgorithmique
EnaucunendroitlanormeC++nespcifielamanirederaliserunefonctionnalit. Eneffet, elle
nimposenilesstructuresdedonnes,nilesalgorithmesutiliser.Lesseuleschosesquisontsp
cifiesparlanormesontlesinterfacesbienentendu(cestdirelesnomsdesclasses,desobjetset
lessignaturesdesfonctionsetdesmthodes)etlasmantiquedesdiversesoprationsralisables.Ce
pendant,lanormeC++nepermetpasderalisertoutescesfonctionnalitsnimportecomment,car
elleimposegalementdescontraintesdeperformancessurlaplupartdesesalgorithmesainsiquesur
lesmthodesdesconteneurs.Cescontraintessontexprimesgnralemententermedecomplexit
algorithmique,aussiestilncessairedeprciserunpeucettenotion.
Note:Enpratique,lescontraintesdecomplexitimposesparlabibliothquestandardsonttout
simplementlesplusfortesralisables.Endautrestermes,onnepeutpasfairemieuxqueles
algorithmesdelabibliothquestandard.

13.7.1.Gnralits
Lanaturedeschosesveutqueplusunprogrammeadedonnestraiter,plusilprenddutempspour
lefaire. Cependant, certainsalgorithmessecomportentmieuxquedautreslorsquelenombredes
donnestraiteraugmente. Parexemple, unalgorithmemalcritpeutvoirsontempsdexcution
crotreexponentiellementaveclaquantitdedonnestraiter, alorsquunalgorithmebientudi
auraitnauraittpluslentqueproportionnellementcemmenombre.Enpratique,celasignifieque
cetalgorithmeesttoutsimplementinutilisablelorsquelenombrededonnesaugmente.Parexemple,
lefaitdedoublerlatailledelensembledesdonnestraiterpeutengendreruntempsdecalculquatre
foispluslong,alorsqueletempsdexcutiondelalgorithmebiencritnauraittquedudouble
seulement.Etsilenombrededonnesesttripletnondoubl,cetalgorithmedemanderahuitfoisplus
detemps,loletripleseulementestncessaire.Silonprendquatrefoisplusdedonnes,letemps

229

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
seramultipliparsoixantequatre. Onvoit clairement queleschosesnevont pasensamliorant
quandlenombrededonnestraiteraugmente...
Enralit,ilestrelativementraredeconsidrerletempsdexcutionpourqualifierlesperformances
dunalgorithme.Eneffet,lecalculdutempsdexcutionnestpastoujourspossibledunepart,parce
quilsebasesurdesparamtresaprioriinconnus,etnestpastoujourscequiestintressantauni
veauducotdautrepart.Pourillustrercedernierpoint,supposonsquechaqueoprationeffectue
parlalgorithmecoteunecertainequantitdnergie.Danscertainscontextes,ilestplusimportant
desintresserlnergiedpensequautempspasspoureffectuerlensembledestraitements.Or
certainesoprationspeuventprendrerelativementpeudetemps,maiscotertrschernergtique
mentparlant,etloptimisationdutempsdexcutionnedonnepasforcmentlameilleuresolution.
Unautreexempleesttoutsimplementceluidelalecturedesecteurssurundisquedur.Lalecturede
cessecteursensoineprendpastellementdetemps,enrevancheledplacementdelattedelecture
sefaitenuntempsdaccsconsidrablementplusgrand.
Lesalgorithmesdegestiondesentres/
sortiessurdisquedessystmesdexploitationcherchentdoncnaturellementdiminueraumaximum
cesdplacementsenrorganisantenconsquencelesrequtesdelectureetdcriture.
Il est doncgnralement beaucoupplussimpledecompterlenombredoprationsquelesalgo
rithmeseffectuentlorsdeleurdroulement,carcettedonneestbienmoinsspcifiqueaucontexte
dutilisationdelalgorithme.Bienentendu,touteslesoprationseffectuesparunalgorithmenont
paslemmecotdansuncontextedonn,etdepluscecotvarieduncontextedutilisationun
autre.Lacomplexitdunalgorithmedoitdonctoujourssexprimerennombredoprationslmen
tairesduncertaintype,tantentenduquelesoprationsdecetypesontcellesquicotentlepluscher
selonlescritreschoisis...
Remarquezquelesoprationsquisontralisesparunalgorithmepeuventtreellesmmesrelative
mentcomplexes.Parexemple,unalgorithmequiappliqueunefonctionsurchaquedonnetraiter
peututiliserunefonctioninimaginablementcomplexe.Cependant,celanenousintressepasdansla
dterminationdelacomplexitdecetalgorithme.Bienentendu,cequilfautcompter,cestlenombre
defoisquecettefonctionestappele,etlacomplexitdelalgorithmedoitsecalculerindpendam
mentdecelledecettefonction.Loprationlmentairedelalgorithmeestdoncicitoutsimplement
lappeldecettefonction,aussicomplexesoitelle.

13.7.2.Notionsmathmatiquesdebaseetdfinition
Lenombredesoprationslmentaireseffectuesparunalgorithmeest
unefonctiondirectedu
nombrededonnestraiter. Lacomplexitdunalgorithmeest doncdirectement reliecette
fonction: plusellecrot rapidement aveclenombrededonnestraiter,
pluslacomplexitde
lalgorithmeestgrande.
Enralit, lafonctionexactedonnantlenombredoprationslmentaireseffectuesparunalgo
rithmenestpastoujoursfacilecalculer.Cependant,ilexistetoujoursunefonctionplussimplequi
disposedummecomportementquelafonctiondunombredoprationsdelalgorithmequandle
nombrededonnestraiteraugmente. Cetteformesimplifienestenfaitriendautrequela
partiecroissantleplusviteaveclenombrededonnes,carlorsqueceluicitendverslinfini,cest
ellequidevientprdominante.Celasignifiequesilontracelegraphedelafonction,saformefinit
parressemblercelledesaformesimplifielorsquelenombrededonnestraiterdevientgrand.
Laformulationcompltedelafonctiondunombredoprationsralisesparunalgorithmenimporte
doncpastantquecela,cequiestintressant,cestsaformesimplifie.Eneffet,nonseulementelleest
plussimple(exprimer,manipuleretbienvidemmentretenir),maisenplusellecaractrisecor
rectementlecomportementdelalgorithmesurlesgrandsnombres.Lacomplexitdunalgorithme
estdonc,pardfinition,letermeprpondrantdanslafonctiondonnantlenombredoprationsl
mentaireseffectuesparlalgorithmeenfonctiondunombredesdonnestraiter.

230

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
Mathmatiquement parlant, lefait quelaformesimplifiedunefonctionsecomportecommela
fonctionellemmelinfinisetraduitsimplementendisantquelestermesdordreinfrieurssont
crassparletermedepremierordre. Parconsquent, si londiviseunefonctionparlautre, les
termesdordreinfrieurdeviennentngligeablesetlavaleurdurapporttendsestabiliserversles
grandnombres.Autrementdit,ilestpossibledetrouverdeuxconstantes A et B positivesetnonnulles
tellesque,partirdunecertainevaleurde n,latripleinquation0 Ac(n) f(n) Bc(n),
danslaquelle c(n) estlaformesimplifiedelafonctionf(n),esttoujoursvrifie.Lafonctionf(n)
estdonc,enquelquesortes,encadrepardeuxgendarmesquisuiventlemmetrajet:celuide
lafonction c(n).
f(n) et c(n) directement.
Note:Notezquecetteformulationnutilisepaslerapportdesfonctions
Elleestdonctoujoursvalide,mmelorsquecesdeuxfonctionssontnulles,cequiauraitposdes
problmessilonavaitutilisunrapport.

Enfait,lalimiteinfrieure Ac(n) nenousintressepasspcialement.Eneffet,seullecotmaximal


dunalgorithmeestintressant,carsilcotemoinscherqueprvu,personnenesenplaindra...Ilest
donccourantdutiliseruneformulationplussimpleetplusconnuedesmathmaticiens,danslaquelle
seuleladernireinquationestutilise.Onditalorsquelafonction f(n) estengrandOde c(n) (ce
quisenote O(c(n)) ).Celasignifiequilexisteuneconstante A telleque,pourtouteslesvaleurs
de n suprieuresunevaleursuffisammentgrande,ladoubleinquation 0 f(n) Ac(n) est
toujoursvrifie.
Note:LanotiondegrandOpermetdoncdedonnerunebornesuprieuredelacomplexitde
lafonction.Enfait,si f(n) esten O(c(n)),ellelestpourtouteslesfonctionsplusgrandesque
c(n).Toutefois,engnral,oncherchedterminerlapluspetitefonction
c(n) quiestungrand
Ode f(n).
Ilestvidentquesiunefonctionf(n) disposeduneformesimplifiec(n),elleestenO(c(n)).En
effet,linquationsuprieureesttoujoursvrifie,onnefaiticiquignorerladeuximeinquation
deladfinitiondelaformesimplifie.

13.7.3.Interprtationpratiquedelacomplexit
Toutescesnotionspeuventvousparatreassezabstraites,maisilestimportantdebiencomprendrece
quellessignifient.Ilestdoncpeuttrencessairededonnerquelquesexemplesdecomplexitparmi
cellesquelonrencontrelepluscouramment.
Tout dabord, unecomplexitde 1 pour unalgorithmesignifietout simplement quesoncot
dexcutionestconstant,quelquesoitlenombrededonnestraiter.Notezbieniciquelonparle
decotdexcutionetnondedure.Lecotesticilenombredoprationslmentaireseffectues
parcetalgorithme.Lesalgorithmesdecomplexit 1 sontvidemmentlesplusintressants,maisils
sonthlasassezraresoutoutsimplementtriviaux.
Gnralement,lesalgorithmesontunecomplexitde n,leurcotdexcutionestdoncproportionnel
aunombrededonnestraiter.Cestencoreunelimiteacceptable,etgnralementacceptecomme
uneconsquencelogiquedelaugmentationdunombrededonnestraiter.Certainsalgorithmes
n2 ,soitlecarrdunombre
sontenrevanchenettementmoinsperformantsetontunecomplexiten
deslmentstraiter. Cettefois, celasignifiequeleurcot dexcutionatendancecrotretrs
rapidementlorsquilyadeplusenplusdedonnes.Parexemple,silondoublelenombrededonnes,
lecot dexcutiondelalgorithmenedoublepas, maisquadruple. Et si lontriplelenombrede

231

Chapitre13.Servicesetnotionsdebasedelabibliothquestandard
donnes,cecotdevientneuffoisplusgrand.Necroyezpaspourautantquelesalgorithmesdece
typesoientraresoumauvais.Onnepeutpastoujours,hlas,faireautrement...
Ilexistemmedesalgorithmesencorepluscoteux,quiutilisentdesexposantsbiensuprieurs2.
Inversement,certainsalgorithmesextrmementastucieuxpermettentderduirelescomplexits n ou
n2 en ln(n) ou nln(n),ilssontdoncnettementplusefficaces.
Note: Lafonction ln(n) est lafonctionlogarithmique, qui est lafonctioninversede
lexponentielle, bienconnuepour sacroissancedmesure. Lafonctionlogarithmevolue
beaucoupmoinsvitequesonargument,enloccurrence n dansnotrecas,etadonctendance
craserlecotdesalgorithmesquilontpourcomplexit.

Enfin,pourterminercesquelquesnotionsdecomplexitalgorithmique,sachezquelonpeutvaluer
ladifficultdunproblmepartirdelacomplexitdumeilleuralgorithmequipermetdelersoudre.
Parexemple,ilatdmontrqueletridunensemblede n lmentsnepeutpassefaireenmieux
que nln(n) oprations(etonsaitlefaire, cequiestsansdouteleplusintressantdelaffaire).
Malheureusement, ilnestpastoujoursfacilededterminerlacomplexitdunproblme.
Ilexiste
mmetouteuneclassedeproblmesextrmementdifficilesrsoudrepourlesquelsonnesaitmme
passi leursolutionoptimaleest polynomialeounon. Enfait, onnesait lesrsoudrequavecdes
algorithmesdecomplexitexponentielle(sivousnesavezpascequecelasignifie,enunmot,cela
veutdirequecestunevritablecatastrophe).Cependant,celaneveutpasforcmentdirequonne
peutpasfairemieux,maistoutsimplementquonnapasputrouverunemeilleuresolution,nimme
prouverquilyenavaitune!Toutefois, touscesproblmessontliset, siontrouveunesolution
polynomialepourlundentreeux,onsaurarsoudreaussifacilementtoussespetitscamarades.Ces
problmesappartiennenttouslaclassedesproblmesditsNPcomplets.

232

Chapitre14.Lestypescomplmentaires
LeC++tant unlangagebassurleC, il souffredesmmeslimitationsconcernant lestypesde
donnesavancsqueceluici. Pourpalliercet inconvnient, labibliothquestandardC++dfinit
destypescomplmentairessousformedeclassesC++,ventuellement template,etpermettantde
satisfaireauxbesoinslespluscourants. Parmicestypes, onnoteraavanttoutletypebasic_string,
quipermetdemanipulerleschanesdecaractresdemanireplussimpleetplussrequavecdes
pointeursetdestableauxdecaractres.Maislabibliothquestandarddfinitgalementdesclasses
utilitairesquipermettentdemanipulerlesautrestypesplusfacilement,ainsiquedestypescapables
dutilisertouteslesressourcesdelamachinepourlescalculsnumriquesavancs.

14.1.Leschanesdecaractres
Laclasse template basic_stringdelabibliothquestandard,dclaredanslenttestring,facilite
letravailduprogrammeuretpermetdcrireducodemanipulantdestextesdemanirebeaucoup
plussre. Eneffet, cetteclasseencapsuleleschanesdecaractresCclassiquesetfournissentdes
servicesextrmementintressantsquintaientpasdisponiblesauparavant.Enparticulier,laclasse
basic_stringdisposedescaractristiquessuivantes:

compatibilitquasitotaleavecleschanesdecaractresCstandards;

gestiondeschanestaillevariable;

priseenchargedelallocationdynamiquedelammoireetdesalibrationenfonctiondesbesoins
etdelatailledeschanesmanipules;

dfinitiondesoprateursdeconcatnation,
cherchedansleschanesdecaractres;

intgrationtotaledanslabibliothquestandard,enparticulierauniveaudesfluxdentre/sortie.

decomparaisonet desprincipalesmthodesdere

Commeillatditplushaut,laclassebasic_stringestuneclasse template.Celasignifiequelle
estcapabledeprendreenchargedeschanesdenimportequeltypedecaractre.Pourcela,ellene
sebasequesurlaclassedestraitsdutypedecaractremanipul.Ilestdoncparfaitementpossible
delutiliseravecdestypesdfinisparlutilisateur, pourvuquelaclassedestraitsdescaractres
soitdfiniepourcestypes. Bienentendu, laclassebasic_stringpeuttreutiliseaveclestypesde
caractresdulangage,savoircharetwchar_t.
Lesdclarationsdelentte string sontessentiellementlessuivantes:
template <classcharT,classtraits=char_traits
<charT>,
classAllocator=allocator
<charT>>
classbasic_string
{
public:
//Types
typedeftraits
traits_type;
typedeftypenametraits::char_typevalue_type;
typedefAllocator
allocator_type;
typedeftypenameAllocator::size_type
size_type;
typedeftypenameAllocator::difference_typedifference_type;
typedeftypenameAllocator::reference
reference_type;
typedeftypenameAllocator::const_referenceconst_reference;

233

Chapitre14.Lestypescomplmentaires
typedeftypenameAllocator::pointer
typedeftypenameAllocator::const_pointer

pointer;
const_pointer;

//Constanteutiliseeninterneetreprsentantlavaleurmaximale
//dutypesize_type:
staticconstsize_typenpos=static_cast <size_type>(1);
//Constructeursetdestructeur:
explicitbasic_string(constAllocator&allocateur=Allocator());
basic_string(constbasic_string&source,size_typedebut=0,
size_typefin=npos,constAllocator&allocateur=Allocator());
basic_string(constcharT*chaine,size_typenombre,
constAllocator&allocateur=Allocator());
basic_string(constcharT*chaine,
constAllocator&allocateur=Allocator());
basic_string(size_typenombre,charTcaractere,
constAllocator&allocateur =Allocator());
template <classInputIterator>
basic_string(InputIteratordebut,InputIteratorfin,
constAllocator&allocateur =Allocator());
~basic_string();
//Itrateurs:
typedeftype_priviterator;
typedeftype_privconstiterator;
typedefstd::reverse_iterator
<iterator> reverse_iterator;
typedefstd::reverse_iterator
<const_iterator> const_reverse_iterator;
iterator
begin();
const_iteratorbegin()const;
iterator
end();
const_iteratorend()const;
reverse_iterator
rbegin();
const_reverse_iteratorrbegin()const;
reverse_iterator
rend();
const_reverse_iteratorrend()const;
//Accesseurs:
size_typesize()const;
size_typelength()const;
size_typemax_size()const;
size_typecapacity()const;
boolempty()const;
allocator_typeget_allocator()const;
//Manipulateurs:
voidresize(size_typetaille,charTcaractere);
voidresize(size_typetaille);
voidreserve(size_typetaille=0);
//Accsauxdonnesdelachane:
const_referenceoperator[](size_typeindex)const;
referenceoperator[](size_typeindex);
const_referenceat(size_typeindex)const;
referenceat(size_typeindex);
constcharT*c_str()const;
constcharT*data()const;
size_typecopy(charT*destination,size_typetaille,

234

Chapitre14.Lestypescomplmentaires
size_typedebut=0)const;
basic_stringsubstr(size_typedebut=0,size_typetaille=npos)const;
//Affectation:
basic_string&operator=(constbasic_string&source);
basic_string&operator=(constcharT*source);
basic_string&operator=(charTcaractere);
basic_string&assign(constbasic_string&source);
basic_string&assign(constbasic_string&source,
size_typeposition,size_typenombre);
basic_string&assign(constcharT*chaine,size_typenombre);
basic_string&assign(constcharT*chaine);
basic_string&assign(size_typenombre,charTcaractere);
template <classInputIterator>
basic_string&assign(InputIteratordebut,InputIteratorfin);
//Concatnationetajout:
basic_string&operator+=(constbasic_string&source);
basic_string&operator+=(constcharT*chaine);
basic_string&operator+=(charTcaractere);
basic_string&append(constbasic_string&source);
basic_string&append(constbasic_string&source,
size_typeposition,size_typenombre);
basic_string&append(constcharT*chaine,size_typenombre);
basic_string&append(constcharT*chaine);
basic_string&append(size_typenombre,charTcaractere);
template <classInputIterator>
basic_string&append(InputIteratordebut,InputIteratorfin);
//Insertionetextraction:
basic_string&insert(size_typeposition,constbasic_string&source);
basic_string&insert(size_typeposition,constbasic_string&source,
size_typedebut,size_typenombre);
basic_string&insert(size_typeposition,constcharT*chaine,
size_typenombre);
basic_string&insert(size_typeposition,constcharT*chaine);
basic_string&insert(size_typeposition,size_typenombre,
charTcaractere);
iteratorinsert(iteratorposition,charTcaractere=charT());
voidinsert(iteratorposition,size_typenombre,charTcaractere);
template <classInputIterator>
voidinsert(iteratorposition,InputIteratordebut,InputIteratorfin);
//Suppression:
basic_string&erase(size_typedebut=0,size_typefin=npos);
iteratorerase(iteratorposition);
iteratorerase(iteratordebut,iteratorfin);
voidclear();
//Remplacementetchange:
basic_stringreplace(size_typeposition,size_typelongueur,
constbasic_string&remplacement);
basic_stringreplace(size_typeposition,size_typelongueur,
constbasic_string&remplacement,size_typedebut,
size_typetaille);
basic_string&replace(size_typeposition,size_typelongueur,
constcharT*remplacement,size_typetaille);

235

Chapitre14.Lestypescomplmentaires
basic_string&replace(size_typeposition,size_typelongueur,
constcharT*remplacement);
basic_string&replace(size_typeposition,size_typelongueur,
size_typenombre,charTcaractere);
basic_string&replace(iteratordebut,iteratorfin,
constbasic_string&remplacement);
basic_string&replace(iteratordebut,iteratorfin,
constcharT*remplacement,size_typetaille);
basic_string&replace(iteratordebut,iteratorfin,
constcharT*remplacement);
basic_string&replace(iteratordebut,iteratorfin,
size_typenombre,charTcaractere);
template <classInputIterator>
basic_string&replace(iteratordebut,iteratorfin,
InputIteratordebut_remplacement,InputIteratorfin_remplacement);
voidswap(basic_string<charT,traits,Allocator> &chaine);
//Comparaison:
intcompare(constbasic_string&chaine)const;
intcompare(size_typedebut1,size_typelongueur1,
constbasic_string&chaine,
size_typedebut2,size_typelongueur2)const;
intcompare(constcharT*chaine)const;
intcompare(size_typedebut,size_typelongueur,constcharT*chaine,
size_typetaille=npos)const;
//Recherche:
size_typefind(constbasic_string&motif,
size_typeposition=0)const;
size_typefind(constcharT*motif,size_typeposition,
size_typetaille)const;
size_typefind(constcharT*motif,size_typeposition=0)const;
size_typefind(charTcaractere,size_typeposition=0)const;
size_typerfind(constbasic_string&motif,
size_typeposition=npos)const;
size_typerfind(constcharT*motif,size_typeposition,
size_typetaille)const;
size_typerfind(constcharT*motif,size_typeposition=npos)const;
size_typerfind(charTcaractere,size_typeposition=npos)const;
size_typefind_first_of(constbasic_string&motif,
size_typeposition=0)const;
size_typefind_first_of(constcharT*motif,size_typeposition,
size_typetaille)const;
size_typefind_first_of(constcharT*motif,
size_typeposition=0)const;
size_typefind_first_of(charTcaractere,size_typeposition=0)const;
size_typefind_last_of(constbasic_string&motif,
size_typeposition=npos)const;
size_typefind_last_of(constcharT*motif,size_typeposition,
size_typetaille)const;
size_typefind_last_of(constcharT*motif,
size_typeposition=npos)const;
size_typefind_last_of(charTcaractere,
size_typeposition=npos)const;
size_typefind_first_not_of(constbasic_string&motif,
size_typeposition=0)const;
size_typefind_first_not_of(constcharT*motif,size_typeposition,

236

Chapitre14.Lestypescomplmentaires
size_typetaille)const;
size_typefind_first_not_of(constcharT*motif,
size_typeposition=0)const;
size_typefind_first_not_of(charTcaractere,
size_typeposition=0)const;
size_typefind_last_not_of(constbasic_string&motif,
size_typeposition=npos)const;
size_typefind_last_not_of(constcharT*motif,size_typeposition,
size_typetaille)const;
size_typefind_last_not_of(constcharT*motif,
size_typeposition=npos)const;
size_typefind_last_not_of(charTcaractere,
size_typeposition=npos)const;
};
typedefbasic_string<char>
string;
typedefbasic_string<wchar_t> wstring;

Lesoprateursdeconcatnation, decomparaisonet desrialisationdanslesfluxdentre/


sortie
sontgalementdfinisdanscetentteetnontpastreportsiciparsoucideclart.Commevous
pouvezlevoir,laclassebasic_stringdisposedungrandnombredemthodes.Nousallonsprsent
lesdtaillerdanslesparagraphessuivants.
Labibliothquestandarddfinitdeuxtypeschanesdecaractrespourlestypesstandardsdecarac
tresdulangage:letypestringpourleschar,etletypewstringpourleswchar_t.Enpratique,ceseront
donccestypesquiserontutilissdanslesprogrammes.Lesexemplesdelasuitedecedocumentuti
liserontdoncletypestring,maisvousteslibredutiliserdesinstancesdelaclassebasic_stringpour
dautrestypesdecaractres.

14.1.1.Constructionetinitialisationdunechane
Lamanirelaplussimpledeconstruireunebasic_stringestsimplementdeladclarer, sanspara
mtres. Celaapourconsquencedappelerleconstructeurpardfaut, etdinitialiserlachanela
chanevide.
Enrevanche,sivousdsirezinitialisercettechane,plusieurspossibilitssoffrentvous.Outrele
constructeurdecopie,quipermetdecopieruneautrebasic_string,ilexisteplusieurssurchargesdu
constructeurpermettantdinitialiserlachanedediffrentesmanires.Leconstructeurleplusutilis
serasansaucundouteleconstructeurquiprendenparamtreunechanedecaractresCclassique:
stringchaine("Valeurinitiale");

Ilexistecependantunevariantedececonstructeur,quiprendenparamtrelenombredecaractres
delachanesourceutiliserpourlinitialisationdelabasic_string.Ceconstructeurdevratreutilis
danslecasdestableauxdecaractres, qui contiennent deschanesdecaractresqui nesont pas
ncessairementterminesparuncaractrenul:
stringchaine("Valeurinitiale",6);

Laligneprcdenteinitialiselachane chaine aveclachanedecaractres "Valeur",carseulsles


sixpremierscaractresdelachanedinitialisationsontutiliss.
Ilestgalementpossibledinitialiserunebasic_stringavecunepartiedechanedecaractresseule
ment.Pourcela,ilfaututiliserleconstructeurtemplate,quiprendenparamtreunitrateurrfren
antlepremiercaractreutiliserlorsdelinitialisationdelabasic_stringetunitrateurrfrenantle

237

Chapitre14.Lestypescomplmentaires
caractresuivantlederniercaractreutiliser.Bienentendu,cesdeuxitrateurssontdesimplespoin
teursdecaractressilescaractresdevantservirlinitialisationsontdansunechanedecaractres
Coudansuntableaudecaractres.Cependant,cepeuttredesitrateursdunconteneurquelconque,
pourvuqueceluicicontiennebienunesquencedecaractresetqueledeuximeitrateursetrouve
bienaprslepremierdanscettesquence.Notezqueledeuximeitrateurnerfrencepasledernier
caractredelasquencedinitialisation,maisbienlecaractresuivant.Ilpeutdoncvaloirlavaleur
defindelitrateurduconteneursource.Ainsi,lecodesuivant:
char*source="Valeurinitiale";
strings(source,source+6);

astrictementlemmeeffetqueceluidelexempleprcdent.
Enfin,ilexisteunconstructeurdontlebutestdinitialiserunebasic_stringavecunesuitedecaractres
identiquesdunecertainelongueur.Ceconstructeurnestrellementpasdifficileutiliser,puisquil
suffitdeluifournirenparamtrelenombredecaractresquelabasic_stringdevraconteniretlavaleur
ducaractrequidevratrerptdanscettechane.
Vousremarquerezquetouscesconstructeursprennentendernierparamtreuneinstancedallocateur
mmoireutiliserpourlesoprationsdallocationetdelibrationdelammoirequelachaneest
susceptibledavoirfaire.Vouspouvezspcifieruneinstancequelconque,ouutiliserlavaleurpar
dfautfournieparlesdclarationsdesconstructeurs.Cettevaleurpardfautesttoutsimplementune
instancetemporairedelallocateurspcifienparamtre template delaclassebasic_string. Par
dfaut,cetallocateurestlallocateurstandard,pourlequeltouteslesinstancespermettentdaccder
lammemmoire.Ilnestdoncpasncessairedespcifierlinstanceutiliser,puisquellessont
toutesfonctionnellementidentiques.Enpratiquedonc,ilesttrsraredavoirspcifierunallocateur
mmoiredanscesconstructeurs.

14.1.2.Accsauxpropritsdunechane
Laclassebasic_stringfournituncertainnombredaccesseurspermettantdobtenirdesinformations
sursontatetsurlachanedecaractresquellecontient.Lunedesinformationslesplusintressantes
estsansnuldoutelalongueurdecettechane. Ellepeuttreobtenuelaidededeuxaccesseurs,
quisontstrictementquivalents: size et length.Vouspouvezutiliserlunoulautre,selonvotre
convenance.Parailleurs,sivousdsirezsimplementsavoirsilabasic_stringestvide,vouspouvez
appelerlamthode empty.
Note:Attention,contrairementcequesonnompourraitlaisserpenser,lamthode empty ne
videpaslabasic_string!

Lataillemaximalequunebasic_stringpeutcontenirestsouventdirectementlielaquantitde
mmoiredisponible,puisquelachanedecaractresquellecontientestallouedynamiquement.Il
nyadoncsouventpasbeaucoupdintrtobtenircettetaille,maisvouspouvezmalgrtoutlefaire,
grcelamthode max_size.
Laquantitdemmoirerellementalloueparunebasic_stringpeuttresuprieurelalongueur
delachanedecaractrescontenue. Eneffet, laclassebasic_stringpeut conserverunemargede
manoeuvre,pourlecasolachanedevraittreagrandielasuiteduneoprationparticulire.Cela
permetderduirelesrallocationsdemmoire,quipeuventtretrscoteuseslorsquelammoire
sefragmente(lachanedoittrerecopieversunnouvelemplacementsiunautreblocmmoirese
trouvejusteaprsleblocmmoirerallouer).Cettequantitdemmoirepeuttreobtenuelaide

238

Chapitre14.Lestypescomplmentaires
delamthode capacity. Nousverronscommentrserverdelaplacemmoireenprvisiondun
redimensionnementultrieurdanslasectionsuivante.
Danslecasovousutiliseriezunallocateurdiffrentdelallocateurpardfaut,vouspouvezobtenir
get_allocator. Ilestrelativementraredavoir
unecopiedecetallocateurgrcelamthode
utilisercettemthode.

14.1.3.Modificationdelatailledeschanes
Unefoisquunebasic_stringatconstruite, ilestpossibledelamodifieraposterioripourlar
duire,lagrandirouaugmentersacapacit.Cesoprationspeuventtreraliseslaidedemthodes
fourniesceteffet.
Lamthode resize permet demodifierlatailledelachanedecaractresstockedanslaba
sic_string. Danssaversionlaplussimple, elleprendenparamtrelanouvelletaillequelachane
doitavoir.Sicettetailleestinfrieurelataillecourante,lachaneesttronque.Enrevanche,sicette
tailleestsuprieurelatailleactuelle,lachaneesttendueetlesnouveauxcaractressontinitiali
ssaveclavaleurdescaractresdfinieparleconstructeurpardfautdeleurclasse.Pourlestypes
prdfinischaretwchar_t, cettevaleuresttoujourslecaractrenul. Lesdonnesstockesdansla
basic_stringreprsententdonctoujourslammechanedecaractresC,puisqueceschanesutilisent
lecaractrenulcommemarqueurdefindechane.Ainsi,lalongueurrenvoyeparlamthode size
peuttrediffrentedelalongueurdelachaneCcontenueparlabasic_string.
Exemple141.Redimensionnementdunechane
#include <iostream>
#include <string>
#include <string.h>
usingnamespacestd;
intmain(void)
{
strings("123");
s.resize(10);
cout << s << endl;
//Lanouvelletaillevautbien10:
cout << "Nouvelletaille:" << s.length() << endl;
//maislalongueurdelachaneCreste3:
cout << "LongueurC:"
<< strlen(s.c_str()) << endl;
return0;
}
Note:Lamthode c_str utilisedanscetexempleseradcriteendtaildanslasectionsuivante.
EllepermetdobtenirladressedelachaneCstockeeninternedanslabasic_string.
Lafonction strlen quantelleestunedesfonctionsdemanipulationdeschanesdecaractres
delabibliothqueC. Elleest dfiniedanslefichierdentte string.h (quelonneconfondra
pasaveclentte string delabibliothquestandardC++),etrenvoielalongueurdelachane
decaractresquiluiestfournieenparamtre.

resize nest
Silavaleurpardfaututilisepourlescaractrescomplmentairesdanslamthode
pascellequiestdsire,ilfautenutiliseruneautreversion.Cettedeuximeversionprend,enplus

239

Chapitre14.Lestypescomplmentaires
delanouvelletailledelachanedecaractres,lecaractrederemplissageutiliserpourlecasola
nouvelletailleseraitsuprieurelatailleinitialedelachane:
strings("123");
s.resize(10,a);

Danscetexemple, s contientfinalementlachanedecaractres "123aaaaaaa".


Nousavonsvuprcdemment quelesbasic_stringtaient susceptiblesdallouerplusdemmoire
quencessairepourstockerleursdonnesafindelimiterlenombrederallocationmmoire.
Ce
mcanismeestcompltementprisenchargeparlabibliothque, etleprogrammeurnaengnral
passensoucier.Cependant,ilpeutexisterdessituationsolonsaitlavancelatailleminimale
quunechanedoitavoirpourpermettredetravaillerdessussanscraindrederallocationsmmoire
successives.Danscecas,onatoutintrtfixerlacapacitdelachanedirectementcettevaleur,
afindoptimiserlestraitements.Celaestralisablelaidedelamthode reserve.Cettemthode
prendenparamtrelacapacitminimalequelabasic_stringdoitavoir.Lanouvellecapacitnestpas
forcmentgaleceparamtreaprscetappel,carlabasic_stringpeutallouerplusdemmoireque
demand.
Exemple142.Rservationdemmoiredansunechane
#include <iostream>
#include <string>
usingnamespacestd;
intmain(void)
{
strings;
cout << s.capacity() << endl;
s.reserve(15);
s="123";
cout << s.capacity() << endl;
return0;
}
Note:Lesmthodes resize et reserve peuventeffectuerunerallocationdelazonemmoire
contenantlachanedecaractres.Parconsquent,touteslesrfrencessurlescaractresde
lachaneettouslesitrateurssurcettechanedeviennentinvalidelasuitedeleurexcution.

14.1.4.Accsauxdonnesdelachanedecaractres
Lescaractresdesbasic_stringpeuventtreaccdsdenombreusesmanires.Premirement,laclasse
basic_stringsurchargeloprateurdaccsauxlmentsduntableau,etlonpourralesutiliserpour
obtenirunerfrenceundescaractresdelachanepartirdesonindice.Cetoprateurnestdfini
quepourlesindicesvalidesdanslachanedecaractres,savoirlesindicesvariantde0lavaleur
retourneparlamthode size delachanemoinsun:
#include <iostream>
#include <string>

240

Chapitre14.Lestypescomplmentaires
usingnamespacestd;
intmain(void)
{
strings("azc");
//Remplaceledeuximecaractredelachaneparunb:
s[1]=b;
cout << s << endl;
return0;
}

Lorsquilestappliquunebasic_stringconstante, loprateurtableaupeutrenvoyerlavaleurdu
caractredontlindiceestexactementlatailledelachane.
Ilsagitvidemmentducaractrenul
servant demarqueurdefindechane. Enrevanche, larfrencerenvoyeparcet oprateurpour
touteslesautresvaleurs,ainsiqueparloprateurtableauappliquauxchanesnonconstantepour
lecaractredefindechanenesontpasvalides.Lecomportementdesprogrammesquieffectuentde
telsaccsestimprvisible.
Ilexisteuneautrepossibilitpouraccderauxcaractresdunebasic_string.Ilsagitdelamthode
at.Contrairementloprateurtableau,cettemthodepermetdeffectueruncontrlesurlavalidit
delindiceutilis.Ellerenvoie,commeloprateurdetableaudelaclassebasic_string,larfrence
ducaractredontlindiceestspcifienparamtre.Cependant,elleeffectueaupralableuncontrle
surlavaliditdecetindice,quidoittoujourstrestrictementinfrieurlatailledelachane.Dansle
cascontraire,lamthode at lanceuneexceptionout_of_range:
#include <iostream>
#include <string>
#include <stdexcept>
usingnamespacestd;
intmain(void)
{
strings("01234");
try
{
s.at(5);
}
catch(constout_of_range&)
{
cout << "Dbordement!" << endl;
}
return0;
}

Laclassebasic_stringnecontientpasdoprateurdetranstypageverslestypesdeschanesdecarac
tresCclassique,savoirletypepointeursurcaractreetpointeursurcaractreconstant.Cestun
choixdeconception,quipermetdviterlesconversionsimplicitesdesbasic_stringenchaneCclas
sique,quipourraienttreextrmementdangereuses.Eneffet,cesconversionsconduiraientobtenir
implicitementdespointeursquineseraientplusvalidesdsquuneoprationseraiteffectuesurla
basic_stringsource.Cependant,laclassebasic_stringfournitdeuxmthodespermettantdobtenirde
telspointeursdemanireexplicite.Leprogrammeurprenddoncsesresponsabilitslorsquilutilise
cesmthodes,etestsuppossavoirdansquelcontextecespointeurssontvalides.

241

Chapitre14.Lestypescomplmentaires
Cesdeuxmthodessontrespectivementlamthodedata etlamthode c_str.Lapremiremthode
renvoieunpointeursurlesdonnesdelabasic_string.Cesdonnesnesontriendautrequuntableau
decaractres, dontladimensionestexactementlavaleurretourneparlamthode size ouparla
mthode length.Cetableaupeutcontenirdescaractresdeterminaisondechane,siparexemple
unetellevaleuratcriteexplicitement ouatintroduitesuiteunredimensionnement dela
chane.Lamthode c_str enrevancheretourneunpointeursurlachanedecaractresCcontenue
danslabasic_string. Contrairement auxdonnesrenvoyesparlamthode data, cettechaneest
ncessairementtermineparuncaractredefindechane.Cettemthodeseradoncutilisepartout
olonveutobtenirunechanedecaractresCclassique, maisellenedevrapastreutilisepour
accderauxdonnessituesaprscecaractredefindechane.
Exemple143.Accsdirectauxdonnesdunechane
#include <iostream>
#include <string>
usingnamespacestd;
intmain(void)
{
strings("123456");
//LachaneCestcoupeautroisimecaractre:
s[3]=0;
cout << s.c_str() << endl;
//Maisonpeutquandmmeobtenirlescaractressuivants:
cout << s.data()[4] << s.data()[5] << endl;
return0;
}

Notezquecesmthodesrenvoientdespointeurssurdesdonnesconstantes.Celaestnormal,caril
estabsolumentinterditdemodifierlesdonnesinterneslabasic_stringquiafournicespointeurs.
Vousnedevezdoncenaucuncasessayerdcriredanscestableauxdecaractres,mmeenfaisant
untranstypageaupralable.
Enfin,laclassebasic_stringdfinitdesitrateursaccsalatoirespermettantdaccdersesdonnes
commesilsagissaitdunechanedecaractresstandard. Lesmthodes begin et end permettent
dobtenirrespectivementunitrateursurlepremiercaractredelachaneetlavaleurdefindece
mmeitrateur.Demme,lesmthodes rbegin et rend permettentdeparcourirlesdonnesdela
basic_stringensensinverse.Prenezgardeaufaitquecesitrateursnesontvalidesquetantquaucune
mthodemodifiantlachanenestappele.

14.1.5.Oprationssurleschanes
Laclassebasic_stringfournittoutunensembledemthodespermettantdeffectuerlesoprationsles
pluscourantessurleschanesdecaractres.Cestcetensembledemthodesquifonttoutlintrt
decetteclasseparrapportauxchanesdecaractresclassiquesdulangageC,carellesprennenten
chargeautomatiquementlesallocationsmmoireetlescopiesdechanesquelimplmentationdeces
fonctionnalitspeutimposer. Cesoprationscomprennentlaffectationetlaconcatnationdedeux
chanesdecaractres,lextractiondunesouschane,ainsiquelasuppressionetleremplacementde
caractresdansunechane.

242

Chapitre14.Lestypescomplmentaires

14.1.5.1.Affectationetconcatnationdechanesdecaractres
Plusieurs surcharges deloprateur daffectationsont dfinies dans laclassebasic_string. Ces
surchargespermettent daffecterunenouvellevaleurunechane, enremplaant ventuellement
lanciennevaleur.Danslecasdunremplacement,lammoireconsommeparlanciennevaleurest
automatiquementrutiliseoulibresiunerallocationestncessaire.Cesoprateursdaffectation
peuventprendreenparamtreuneautrebasic_string,unechanedecaractresCclassiqueoumme
unsimplecaractre. Leurutilisationest doncdirecte, il suffit simplement dcrireuneaffectation
normale.
Ilestimpossible, avecloprateurdaffectation, defournirdesparamtressupplmentairescomme
ceuxdontlesconstructeursdelaclassebasic_stringdisposentparexemple.Cestpourcetteraison
quuneautremthode,lamthode assign,atdfiniepourpermettredefairedesaffectationsplus
complexes.
Lespremiresversionsdecesmthodespermettentbienentendudeffectuerlaffectationduneautre
basic_stringoudunechanedecaractresCclassique.Cependant,ilestgalementpossibledesp
cifierlalongueurdelaportiondechanecopierendeuximeparamtrepourleschanesC,etla
positionainsiquelenombredecaractrescopierdanslecasdunebasic_string.Ilestgalement
possiblederinitialiserunebasic_stringavecuncaractrespcifique, endonnantetlenombrede
caractresdupliquerdanslachaneenpremierparamtreetlavaleurdececaractreendeuxime
paramtre. Enfin, il existeuneversion template decettemthodepermettant daffecterlaba
sic_stringlasquencedecaractrescomprisentredeuxitrateursdunconteneur.
Exemple144.Affectationdechanedecaractres
#include <iostream>
#include <string>
usingnamespacestd;
intmain(void)
{
strings1,s2;
char*p="1234567890";
//Affecte"345"s1:
s1.assign(p+2,p+6);
cout << s1 << endl;
//Affectelesdeuxpremierscaractresdes1s2:
s2.assign(s1,0,2);
cout << s2 << endl;
//Rinitialises1avecdesA:
s1.assign(5,A);
cout << s1 << endl;
return0;
}

Demaniresimilaire,loprateurdaffectationavecaddition +=atsurchargafindepermettre
lesconcatnationsdechanesdecaractresdemanireintuitive.Cetoprateurpermetdajouteraussi
bienuneautrebasic_stringquunechanedecaractresCclassiqueouununiquecaractrelafin
dunebasic_string.Commecetoprateuresttroprestrictiflorsquilsagitdeconcatnerunepartie
append atdfini.Cesm
seulementduneautrechaneunebasic_string,unjeudemthodes
thodespermettentdajouterunebasic_stringuneautrebasic_stringouunechanedecaractresC
bienentendu,maisaussidajouterunepartieseulementdeceschanesouunnombredterminde
caractres.Toutescesmthodesprennentlesmmesparamtresquelesmthodes assign correspon
dantesetleuremploinedevraitpasposerdeproblmeparticulier.

243

Chapitre14.Lestypescomplmentaires
Exemple145.Concatnationdechanesdecarctres
#include <iostream>
#include <string>
usingnamespacestd;
intmain(void)
{
strings1="abcef";
strings2="ghijkl";
//Utilisationdeloprateurdeconcatnation:
s1+=s2;
cout << s1 << endl;
//Utilisationdelamthodeappend:
s1.append("mnopq123456",5);
cout << s1 << endl;
return0;
}

14.1.5.2.Extractiondedonnesdunechanedecaractres
Nousavonsvuquelesmthodes data et c_str permettaientdobtenirdespointeurssurlesdonnes
desbasic_string.Cependant,ilestinterditdemodifierlesdonnesdelabasic_stringautraversdeces
pointeurs.Or,ilpeuttreutile,danscertainessituations,davoirtravaillersurcesdonnes,ilfaut
doncpouvoirenfaireunecopietemporaire. Cestcequepermetlamthode copy. Cettefonction
prendenparamtreunpointeursurunezonedemmoiredevantaccueillirlacopiedesdonnesdela
basic_string,lenombredecaractrescopier,ainsiquelenumroducaractredelabasic_string
partirduquellacopiedoitcommencer.Cedernierparamtreestfacultatif,carilprendpardfautla
valeur0(lacopiesefaitdoncpartirdupremiercaractredelabasic_string.
Exemple146.Copiedetravaildesdonnesdunebasic_string
#include <iostream>
#include <string>
usingnamespacestd;
intmain(void)
{
strings="1234567890";
//Copielachanedecaractresdansunezonedetravail:
charbuffer[16];
s.copy(buffer,s.size(),0);
buffer[s.size()]=0;
cout << buffer << endl;
return0;
}

Labasic_stringdoitcontenirsuffisammentdecaractrespourquelacopiepuissesefaire.Sicenest
paslecas, ellelancerauneexceptionout_of_range. Enrevanche, lamthode copy nepeut faire
aucunevrificationquantlaplacedisponibledanslazonemmoirequiluiestpasseenparamtre.
Ilestdoncdelaresponsabilitduprogrammeurdesassurerquecettezoneestsuffisammentgrande
pouraccueillirtouslescaractresquildemande.

244

Chapitre14.Lestypescomplmentaires
Lamthode copy permet dobtenirlacopiedunesouschanedelachanecontenuedanslaba
sic_string.Toutefois,silonveutstockercettesouschanedansuneautrebasic_string,ilnefautpas
utilisercettemthode.Lamthode substr permeteneffetdeffectuercetravaildirectement.Cette
mthodeprendenpremierparamtrelenumrodupremiercaractrepartirdelasouschaneco
pier,ainsiquesalongueur.Commepourlamthodecopy,ilfautquelabasic_stringsourcecontienne
suffisammentdecaractresfautedequoiuneexceptionout_of_rangeseralance.
Exemple147.Extractiondesouschane
#include <iostream>
#include <string>
usingnamespacestd;
intmain(void)
{
strings1="1234567890";
strings2=s1.substr(2,5);
cout << s2 << endl;
return0;
}

14.1.5.3.Insertionetsuppressiondecaractresdansunechane
Laclassebasic_stringdisposedetoutunjeudemthodesdinsertiondecaractresoudechanesde
caractresauseindunebasic_stringexistante.Toutescesmthodessontdessurchargesdelamthode
insert.Cessurchargesprennenttoutesunparamtreenpremirepositionquiindiquelendroito
linsertiondoittrefaite.Ceparamtrepeuttresoitunnumrodecaractre,indiquparunevaleur
detypesize_type,soitunitrateurdelabasic_stringdanslaquellelinsertiondoittrefaite.Lesautres
paramtrespermettentdespcifiercequidoittreinsrdanscettechane.
Lesversionslesplussimplesdelamthode insert prennentendeuximeparamtreuneautreba
sic_stringouunechanedecaractresCclassique.Leurcontenuserainsrlemplacementindiqu.
Lorsqueledeuximeparamtreestunebasic_string,ilestpossibledindiquerlenumrodupremier
caractreainsiquelenombredecaractrestotalinsrer.Demme,lorsdelinsertiondunechane
Cclassique,ilestpossibledindiquerlenombredecaractresdecettechanequidoiventtreinsrs.
Ilexisteaussidesmthodes insert permettantdinsrerunouplusieurscaractresunemplacement
donndanslachanedecaractres.Cecaractredoitalorsspcifiendeuximeparamtre,saufsi
lonveutinsrerplusieurscaractresidentiquesdanslachane,auquelcasondoitindiquerlenombre
decaractresinsreretlavaleurdececaractre.
Enfin, il existeuneversiondelamthode insert qui prendenparamtre, enplusdelitrateur
spcifiantlapositionpartirdelaquellelinsertiondoittrefaitedanslabasic_string,deuxautresit
rateursdunquelconqueconteneurcontenantdescaractres.Utilisavecdespointeursdecaractres,
cetitrateurpeuttreutilispourinsrerunmorceauquelconquedechanedecaractresCdansune
basic_string.
Toutescesmthodesrenvoientgnralementlabasic_stringsurlaquelleilstravaillent,sauflesm
thodesquiprennentenparamtreunitrateur.Cesmthodessupposenteneffetquelamanipulation
delachanedecaractressefaitparlintermdiairedecetitrateur,etnonparlintermdiairedune
rfrencesurlabasic_string.Cependant,lamthodeinsert permettantdinsreruncaractreunique
unemplacementspcifiparunitrateurrenvoielavaleurdelitrateurrfrenantlecaractrequi
vientdtreinsrafindepermettredercuprercenouvelitrateurpourlesoprationsultrieures.

245

Chapitre14.Lestypescomplmentaires
Exemple148.Insertiondecaractresdansunechane
#include <iostream>
#include <string>
usingnamespacestd;
intmain(void)
{
strings="abef";
//Insreuncetund:
s.insert(2,"cdze",2);
//Idempourgeth,maisavecunebasic_string:
stringgh="gh";
s.insert(6,gh);
cout << s << endl;
return0;
}

Ilexistegalementtroissurchargesdelamthode erase,dontlebutestdesupprimerdescaractres
dansunechaneendcalantlescaractressuivantlescaractressupprimspourremplirlespositions
ainsilibres.Lapremiremthode erase prendenpremierparamtrelapositiondupremiercarac
treetlenombredescaractressupprimer.Ladeuximemthodefonctionnedemaniresimilaire,
maisprendenparamtrelitrateurdedbutetlitrateurdefindelasouschanedecaractresqui
doittresupprime.Enfin,latroisimeversionde erase permetdesupprimerununiquecaractre,
dontlapositionestspcifieencoreunefoisparunitrateur.Cesdeuxderniresmthodesrenvoient
litrateurrfrenantlecaractresuivantlederniercaractrequiatsupprimdelachane.Silny
avaitpasdecaractresaprslederniercaractreeffac,litrateurdefindechaneestrenvoy.
Enfin, ilexisteunemthodeddiepourleffacementcompletdelachanedecaractrescontenue
dansunebasic_string.Cettemthodeestlamthode clear.
Exemple149.Suppressiondecaractresdansunechane
#include <iostream>
#include <string>
usingnamespacestd;
intmain(void)
{
strings="abcdeerrfgh";
//Supprimelafautedefrappe:
s.erase(5,3);
cout << s << endl;
//Effacelachanedecaractrescomplte:
s.clear();
if(s.empty())cout << "Vide!" << endl;
return0;
}

246

Chapitre14.Lestypescomplmentaires

14.1.5.4.Remplacementsdecaractresdunechane
Commepour linsertiondechanesdecaractres,
il existetout unjeudefonctionspermettant
deffectuerunremplacementdunepartiedelachanedecaractresstockedanslesbasic_stringpar
uneautrechanedecaractres. Cesmthodessontnommes replace etsonttoutfaitsimilaires
dansleprincipeauxmthodes insert.Cependant,contrairementcellesci,lesmthodes replace
prennent unparamtresupplmentairepour spcifier lalongueur oulecaractredefindela
souschaneremplacer.Ceparamtredoittrefournijusteaprslepremierparamtre,quiindique
toujourslecaractrededbut delasouschaneremplacer. Il peut tredetypesize_typepour
lesversionsde replace qui travaillent avecdesindices, outreunitrateur, pourlesversions
de replace qui travaillent avecdes itrateurs. Les autres paramtres des fonctions replace
permettentdedcrirelachanederemplacement,etfonctionnentexactementcommelesparamtres
correspondantsdesfonctions insert.
Exemple1410.Remplacementdunesouschanedansunechane
#include <iostream>
#include <string>
usingnamespacestd;
intmain(void)
{
strings="abcerfg";
//Remplaceleeetlerparundetune:
s.replace(3,2,"de");
cout << s << endl;
return0;
}

Danslemmeordredidequeleremplacement, ontrouveralamthode swap delaclasseba


sic_string, quipermetdintervertirlecontenudedeuxchanesdecaractres.
Cettemthodeprend
enparamtreunerfrencesurladeuximechanedecaractres,
aveclaquellelinterversiondoit
trefaite. Lamthode swap pourradevratreutilisedeprfrencepourraliserleschangesde
chanesdecaractres,carelleestoptimiseeteffectueenfaitlchangeparrfrence.Ellepermet
doncdviterdefaireunecopietemporairedelachanedestinationetdcraserlachanesourceavec
cettecopie.
Exemple1411.changeducontenudedeuxchanesdecaractres
#include <iostream>
#include <string>
usingnamespacestd;
intmain(void)
{
strings1="abcd";
strings2="1234";
cout << "s1=" << s1 << endl;
cout << "s2=" << s2 << endl;
//Intervertitlesdeuxchanes:
s1.swap(s2);
cout << "s1=" << s1 << endl;
cout << "s2=" << s2 << endl;

247

Chapitre14.Lestypescomplmentaires
return0;
}

14.1.6.Comparaisondechanesdecaractres
Lacomparaisondesbasic_stringsebasesurlamthode compare,dontplusieurssurchargesexistent
afindepermettredescomparaisonsdiverseset varies. Lesdeuxversionslesplussimplesdela
mthode compare prennentenparamtresoituneautrebasic_string,soitunechanedecaractresC
classique.Elleseffectuentdonclacomparaisondelabasic_stringsurlaquelleellessappliquentavec
ceschanes.Ellesutilisentpourcelalamthode eq delaclassedestraitsdescaractresutilisspar
lachane.Silesdeuxchanesnediffrentqueparleurtaille,lachanelapluscourteseradclare
infrieurelachanelapluslongue.
Lesdeuxautresmthodes compare permettentdeffectuerlacomparaisondesouschanesdecarac
tresentreelles.Ellesprennenttouteslesdeuxlindiceducaractrededbutetlindiceducaractre
defindelasouschanedelabasic_stringsurlaquelleellessontappliques,untroisimeparamtre
indiquantuneautrechanedecaractres,etdesindicesspcifiantladeuximesouschanedanscette
chane.Siletroisimeargumentestunebasic_string,ilfautspcifiergalementlindicededbutet
lindicedefindelasouschane.Enrevanche,silsagitdunechaneCclassique,ladeuximesous
chanecommencetoujoursaupremiercaractredecettechane,etilnefautspcifierquelalongueur
decettesouschane.
Lavaleurrenvoyeparlesmthodescompare estdetypeentier.Cetentierestnulsilesdeuxchanes
sontstrictementgales(etdemmetaille),ngatifsilabasic_stringsurlaquellelamthode compare
estappliqueestpluspetitequelachanepasseenargument,soitentaille,soitausensdelordre
lexicographique,etpositifdanslecascontraire.
Exemple1412.Comparaisonsdechanesdecaractres
#include <iostream>
#include <string>
usingnamespacestd;
intmain(void)
{
constchar*c1="bcderefb";
constchar*c2="bcdetab"; //c2 > c1
constchar*c3="bcderefas";//c3< c1
constchar*c4="bcde";
//c4 < c1
strings1=c1;
if(s1 < c2)cout << "c1 < c2" << endl;
elsecout << "c1 >=c2" << endl;
if(s1.compare(c3)>0)cout << "c1 > c3" << endl;
elsecout << "c1 <=c3" << endl;
if(s1.compare(0,string::npos,c1,4)
>0)
cout << "c1 > c4" << endl;
elsecout << "c1 <=c4" << endl;
return0;
}

Bienentendu,lesoprateursdecomparaisonclassiquessontgalementdfinisafindepermettredes
comparaisonssimplesentrechanedecaractres.Grcecesoprateurs,ilestpossibledemanipuler

248

Chapitre14.Lestypescomplmentaires
lesbasic_stringexactement commelesautrestypesordonnsdulangage. Plusieurssurchargede
cesoprateursonttdfiniesettravaillentaveclesdiffrentstypesdedonnesaveclesquelsilest
possiblepourunebasic_stringdesecomparer.Lemploidecesoprateursestnatureletneposepas
deproblmesparticuliers.
Note:ToutescescomparaisonssebasentsurlordrelexicographiquedulangageC.Autrement
dit, lescomparaisonsentrechanesdecaractresnetiennent pascomptedelalocaleet des
conventionsnationales.Ellessontdonctrsefficaces,maisnepourrontpastreutilisespour
comparerdeschanesdecaractreshumainementlisibles.Voustrouverezdeplusamplesren
seignementssurlamaniredeprendreencompteleslocalesdanslescomparaisonsdechanes
decaractresdansleChapitre16.

14.1.7.Recherchedansleschanes
Lesoprationsderecherchedansleschanesdecaractresconstituentunedesfonctionnalitsdes
chaneslespluscourantes.Ellesconstituentlaplupartdesoprationsdanalysedeschanes,etsont
souventlependantdelaconstructionetlaconcatnationdechanes.Laclassebasic_stringfournit
donctoutunensembledemthodespermettantdeffectuerdesrecherchesdecaractresoudesous
chanesdansunebasic_string.
Lesfonctionsderecherchesonttoutessurchargesafindepermettredespcifierlapositionpartir
delaquellelarecherchedoitcommencerdunepart,etlemotifdecaractrerechercher.Lepremier
paramtreindiquetoujoursquelestcemotif, quecesoituneautrebasic_string, unechanedeca
ractresCclassiqueouunsimplecaractre. Ledeuximeparamtreestlenumroducaractrede
labasic_stringsurlaquellelamthodederecherchesappliqueetpartirduquelleellecommence.
Cedeuximeparamtrepeuttreutilispoureffectuerplusieursrecherchessuccessives,enrepartant
deladernirepositiontrouvechaquefois.Lorsdunepremirerechercheoulorsdunerecherche
unique,ilnestpasncessairededonnerlavaleurdeceparamtre,carlesmthodesderechercheuti
lisentlavaleurpardfautquiconvient(soitledbutdelachane,soitlafin,selonlesensderecherche
utilisparlamthode).Lesparamtressuivantspermettentdedonnerdesinformationscomplmen
tairessurlemotifutiliserpourlarecherche.Ilnestutilisquelorsquelemotifestunechanede
caractresCclassique.Danscecas,ilesteneffetpossibledespcifierlalongueurdumotifdanscette
chane.
Lesdiffrentesfonctionsderecherchedisponiblessontprsentesdansletableausuivant:
Tableau141.Fonctionsderecherchedansleschanesdecaractres
Mthode

Description

find

Cettemthodepermetderechercherlasouschanecorrespondantau
motifpassenparamtredanslabasic_stringsurlaquelleelleest
applique.Elleretournelindicedelapremireoccurrencedecemotif
danslachanedecaractres,oulavaleur npos silemotifnyapparat
pas.

rfind

Cettemthodepermetdeffectuerunerecherchesimilairecelledela
mthode find,maisenparcourantlachanedecaractresensensinverse.
Notezbienquecenestpaslemotifquiestinversici,maislesensde
parcoursdelachane.Ainsi,lamthode rfind retournelindicedela
dernireoccurrencedumotifdanslachane,oulavaleur npos silemotif
napasttrouv.

249

Chapitre14.Lestypescomplmentaires
Mthode

Description

find_first_of

Cettemthodepermetderechercherlapremireoccurrencedundes
caractresprsentsdanslemotiffournienparamtre.Ilnesagitdonc
plusdunerecherchedechanedecaractres,maisdelarecherchedetous
lescaractresdunensembledonn.Lavaleurretourneestlindicedu
caractretrouv,oulavaleur npos siaucuncaractredumotifnest
dtectdanslachane.

find_last_of

Cettemthodeestlamthode find_first_of ceque rfind est


find.Elleeffectuelarechercheduderniercaractredelabasic_string
quisetrouvedanslalistedescaractresdumotiffournienparamtre.La
valeurretourneestlindicedececaractresilexiste,et npos sinon.

find_first_not_of

Cettemthodetravailleenlogiqueinverseparrapportlamthode
find_first_of.Eneffet,ellerecherchelepremiercaractredela
basic_stringquinestpasdanslemotiffournienparamtre.Ellerenvoie
lindicedececaractre,ou npos siceluicinexistepas.

find_last_not_of

Cettemthodeeffectuelemmetravailquelamthode
find_first_not_of,maisenparcourantlachanedecaractressource
ensensinverse.Elledterminedonclindicedupremiercaractreen
partantdelafinquinesetrouvepasdanslemotiffournienparamtre.
Ellerenvoie npos siaucuncaractrenecorrespondcecritre.

Exemple1413.Recherchesdansleschanesdecaractres
#include <iostream>
#include <string>
usingnamespacestd;
intmain(void)
{
strings="Bonjour tout
lemonde!";
//Recherchelemot"monde":
string::size_typepos=s.find("monde");
cout << pos << endl;
//Recherchelemot"tout"encommenantparlafin:
pos=s.rfind("tout");
cout << pos << endl;
//Dcomposelachaneenmots:
string::size_typedebut=s.find_first_not_of("\t\n");
while(debut!=string::npos)
{
//Recherchelafindumotsuivant:
pos=s.find_first_of("\t\n",debut);
//Affichelemot:
if(pos!=string::npos)
cout << s.substr(debut,posdebut)<< endl;
else
cout << s.substr(debut) << endl;
debut=s.find_first_not_of("\t\n",pos);
}
return0;
}

250

Chapitre14.Lestypescomplmentaires
Note:Toutescesfonctionsderechercheutilisent lordrelexicographiquedulangageCpour
effectuerleurtravail.Ellespeuventdoncnepasconvenirpoureffectuerdesrecherchesdansdes
chanesdecaractressaisiespardeshumains,carellesneprennentpasencomptelalocaleet
lesparamtresnationauxdelutilisateur.Laraisondecechoixestessentiellementlarecherche
delefficacitdanslabibliothquestandard. NousverronsdansleChapitre16lamanirede
procderpourprendreencomptelesparamtresnationauxauniveaudeschanesdecaractres.

14.1.8.Fonctionsdentre/sortiedeschanesde
caractres
Pourterminercetourdhorizondeschanesdecaractres,signalonsquelabibliothquestandardC++
fournitdesoprateurspermettantdeffectuerdescrituresetdeslecturessurlesfluxdentre/sortie.
Lesoprateurs <<et >>sontdoncsurchargspourlesbasic_string,etpermettentdemanipuler
cellescicommedestypesnormaux.Loprateur<<permetdenvoyerlecontenudelabasic_string
surlefluxdesortiestandard.Loprateur >>litlesdonnesdufluxdentrestandard,etlesaffecte
labasic_stringquilreoitenparamtre.Ilsarrtedsquilrencontrelecaractredefindefichier,
unespace,ouquelataillemaximaledesbasic_stringatatteinte(casimprobable):
#include <iostream>
#include <string>
usingnamespacestd;
intmain(void)
{
strings1,s2;
cin >> s1;
cin >> s2;
cout << "Premiermot:" << endl << s1 << endl;
cout << "Deuximemot:" << endl << s2 << endl;
return0;
}

Cependant,cesoprateurspeuventnepassavrersuffisants.Eneffet,lunedesprincipalesdifficults
danslesprogrammesquimanipulentdeschanesdecaractresestdelirelesdonnesquiproviennent
dunfluxdentreligneparligne. Lanotiondelignenestpastrsclaire, etdpendfortementde
lenvironnementdexcution.LabibliothquestandardC++suppose,quantelle,queleslignessont
dlimitesparuncaractrespcialservant demarqueurspcial. Gnralement, cecaractreestle
caractre \n,maisilestgalementpossibledutiliserdautressparateurs.
Poursimplifierlesoprationsdelecturedetextesconstitusdelignes,labibliothquefournitlafonc
tion getline.Cettefonctionprendenpremierparamtrelefluxdentresurlequelelledoitlirela
ligne,etlabasic_stringdanslaquelleelledoitstockercetteligneendeuximeparamtre.Letroisime
paramtrepermetdindiquerlecaractresparateurdeligne.Ceparamtreestfacultatif,carildispose
dunevaleurpardfautquicorrespondaucaractredefindeligneclassique\n.
Exemple1414.Lecturedelignessurlefluxdentre
#include <iostream>
#include <string>

251

Chapitre14.Lestypescomplmentaires

usingnamespacestd;
intmain(void)
{
strings1,s2;
getline(cin,s1);
getline(cin,s2);
cout << "Premireligne:"
cout << "Deuximeligne:"
return0;
}

<< s1 << endl;


<< s2 << endl;

14.2.Lestypesutilitaires
Labibliothquestandardutiliseeninterneuncertainnombredetypesdedonnesspcifiques,
es
sentiellementdansunbutdesimplicitetdefacilitdcriture.Cestypesserontengnralrarement
utilissparlesprogrammeurs, maiscertainesfonctionnalitsdelabibliothquestandardpeuventy
avoirrecours.Ilfautdoncconnatreleurexistenceetsavoirlesmanipulercorrectement.

14.2.1.Lespointeursauto
Laplupartdesvariablesdtruisentleurcontenulorsquellessontdtruitesellesmmes.Uneexception
notablececomportementestbienentenducelledespointeurs,quipardfinitionnecontiennentpas
euxmmesleursdonnesmaispluttunerfrencesurcellesci.Lorsquecesdonnessontalloues
dynamiquement,ilfautsystmatiquementpenserlesdtruiremanuellementlorsquonnenaplus
besoin. Celapeutconduiredesfuitesdemmoire(MemoryLeakenanglais)trsfacilement.
Sidetellesfuitesnesontpasgnantespourlesprocessusdontladuredevieesttrscourte,elles
peuventltreconsidrablementpluspourlesprocessusdestinsfonctionnerlongtemps,sicenest
enpermanence,surunemachine.
Enfait, dansuncertainnombredecas, lallocationdynamiquedemmoirenestutilisequepour
effectuerlocalementdesoprationssurunnombrearbitrairededonnesquinepeuttreconnuqu
lexcution. Cependant, ilestrelativementraredavoirconservercesdonnessurdelonguesp
riodes, et il est souvent souhaitablequecesdonnessoient dtruiteslorsquelafonctionqui lesa
allouessetermine.Autrementdit,ilfaudraitquelespointeursdtruisentautomatiquementlesdon
nesquilsrfrencentlorsquilssonteuxmmesdtruits.
LabibliothquestandardC++fournitceteffetuneclassedencapsulationdespointeurs,quipermet
dobtenircesfonctionnalits. Cetteclassesenommeauto_ptr, enraisondufait quesesinstances
sontutilisescommedespointeursdedonnesdontlaporteestlammequecelledesvariables
automatiques.Ladclarationdecetteclasseestralisecommesuitdanslentte memory :
template <classT >
classauto_ptr
{
public:
typedefTelement_type;
explicitauto_ptr(T*pointeur=0)throw();
auto_ptr(constauto_ptr&source)throw();
template <classU >
auto_ptr(constauto_ptr<U> &source)throw();

252

Chapitre14.Lestypescomplmentaires
~auto_ptr()throw();
auto_ptr&operator=(constauto_ptr&source)throw();
template <classU >
auto_ptr&operator=(constauto_ptr
<U> &source)throw();
T&operator*()constthrow();
T*operator>()constthrow();
T*get()constthrow();
T*release()constthrow();
};

Cetteclassepermetdeconstruireunobjetcontrlantunpointeursurunautreobjetalloudynami
quementavecloprateur new.Lorsquilestdtruit,lobjetrfrencestautomatiquementdtruitpar
unappelloprateur delete.Cetteclasseutilisedoncunesmantiquedepropritstrictedelobjet
contenu,puisquelepointeurainsicontrlnedoittredtruitquuneseulefois.
Celaimpliqueplusieursremarques. Premirement, il yancessairement untransfert deproprit
dupointeurencapsullorsdesoprationsdecopieetdaffectation.Deuximement,touteopration
susceptibledeprovoquerlapertedupointeurencapsulprovoquesadestructionautomatiquement.
Cestnotammentlecaslorsquuneaffectationduneautrevaleurestfaitesurunauto_ptrcontenant
djunpointeurvalide.Enfin,ilnefautjamaisdtruiresoimmelobjetpointunefoisquelona
affectunpointeursurceluiciunauto_ptr.
Il est trssimpledutiliserlespointeursautomatiques. Eneffet, il suffit delesinitialiserleur
constructionaveclavaleurdupointeursurlobjetalloudynamiquement.
Dslors, ilestpossible
dutiliserlauto_ptrcommelepointeuroriginal,puisquildfinitlesoprateurs*et >.
Lesauto_ptrsontsouventutilissentantquevariableautomatiquedanslessectionsdecodesuscep
tibledelancerdesexceptions,puisquelaremontedesexceptionsdtruitlesvariablesautomatiques.
Ilnestdoncplusncessairedetraitercesexceptionsetdedtruiremanuellementlesobjetsallous
dynamiquementavantderelancerlexception.
Exemple1415.Utilisationdespointeursautomatiques
#include <iostream>
#include <memory>
usingnamespacestd;
classA
{
public:
A()
{
cout << "Constructeur" << endl;
}
~A()
{
cout << "Destructeur" << endl;
}
};
//Fonctionsusceptibledelanceruneexception:

253

Chapitre14.Lestypescomplmentaires
voidf()
//Allouedynamiquementunobjet:
auto_ptr<A> p(newA);
//Lanceuneexception,enlaissantaupointeur
//automatiquelesoindedtruirelobjetallou:
throw2;
}
intmain(void)
{
try
{
f();
}
catch(...)
{
}
return0;
}
Note:Onprendrabiengardeaufaitquelacopiedunauto_ptrdansunautreeffectueuntrans
fert deproprit. Celapeut provoquerdessurprises, notamment si lonutilisedesparamtres
defonctionsdetypeauto_ptr(choseexpressment dconseille). Eneffet, il yaurasystma
tiquementtransfertdepropritdelobjetlorsdelappel delafonction,etcestdonclafonction
appelequi enauralaresponsabilit.Si ellenefaitaucuntraitementspcial,lobjetseradtruit
avecleparamtredelafonction,lorsquelexcutionduprogrammeensortira!Inutilededireque
lafonctionappelanterisquedavoirdespetitsproblmes...Pourvitercegenredeproblmes,il
estpluttconseilldepasserlesauto_ptrparrfrenceconstantepluttqueparvaleurdansles
appelsdefonctions.
Unautrepigeclassiqueest dinitialiserunauto_ptravecladressedunobjet qui napast
alloudynamiquement.Ilestfaciledefairecetteconfusion,caronnepeutaprioripasdiresiun
pointeurpointesurunobjetalloudynamiquementounon.Quoiquilensoit,sivousfaitescette
erreur,unappel delete serafaitavecunparamtreincorrectlorsdeladestructiondupointeur
automatiqueetleprogrammeplantera.
Enfin, sachezquelespointeursautomatiquesnutilisent queloprateur delete pourdtruire
lesobjetsquilsencapsulent, jamaisloprateur delete[] . Parconsquent, lespointeursau
tomatiquesnedevront jamaistreinitialissavecdespointeursobtenuslorsduneallocation
dynamiqueavecloprateur new[] ouaveclafonction malloc delabibliothqueC.

Ilestpossibledercuprerlavaleurdupointeurprisenchargeparunpointeurautomatiquesimple
ment,grcelamthode get.Celapermetdetravailleraveclepointeuroriginal,cependant,ilnefaut
jamaisoublierquecestlepointeurautomatiquequienatoujourslaproprit.Ilnefautdoncjamais
appeler delete surlepointeurobtenu.
Enrevanche,silonveutsortirlepointeurdunauto_ptr,etforcerceluicienabandonnerlapro
prit,onpeututiliserlamthode release.Cettemthoderenvoieelleaussilepointeursurlobjet
quelauto_ptrcontenait,maislibregalementlarfrencesurlobjetpointauseindelauto_ptr.
Ainsi,ladestructiondupointeurautomatiqueneprovoqueraplusladestructiondelobjetpointetil
faudranouveauprendreenchargecettedestructionsoimme.

254

Chapitre14.Lestypescomplmentaires
Exemple1416.Sortiedunpointeurdunauto_ptr
#include <iostream>
#include <memory>
usingnamespacestd;
classA
{
public:
A()
{
cout << "Constructeur" << endl;
}
~A()
{
cout << "Destructeur" << endl;
}
};
A*f(void)
{
cout << "Construciondelobjet"<< endl;
auto_ptr<A> p(newA);
cout << "Extractiondupointeur"<< endl;
returnp.release();
}
intmain(void)
{
A*pA=f();
cout << "Destructiondelobjet"<< endl;
deletepA;
return0;
}

14.2.2.Lespaires
Outrelespointeursautomatiques,labibliothquestandardC++dfinituneautreclasseutilitairequi
permet quant elledestockeruncoupledevaleursdansunmmeobjet.
Cetteclasse, laclasse
template pair, est enparticuliertrsutilisedanslimplmentationdecertainsconteneursdela
bibliothque.
Ladclarationdelaclasse template pairestlasuivantedanslentte

utility :

template <classT1,classT2>
structpair
{
typedefT1first_type;
typedefT2second_type;
T1first;
T2second;
pair();

255

Chapitre14.Lestypescomplmentaires
pair(constT1&,constT2&);
template <classU1,classU2>
pair(constpair<U1,U2> &);
};
template <classT1,classT2>
booloperator==(constpair<T1,T2> &,constpair<T1,T2> &);
template <classT1,classT2>
booloperator<(constpair<T1,T2> &,constpair<T1,T2> &);
template <classT1,classT2>
pair<T1,T2> make_pair(constT1&,constT2&);

Commecettedclarationlemontre,lutilisationdelaclassepairestextrmementsimple.Laconstruc
tiondunepairesefaitsoitenfournissantlecoupledevaleursdevanttrestockdanslapaire,soiten
appelantlafonction make_pair.Larcuprationdesdeuxcomposantesdunepairesefaitsimple
mentenaccdantauxdonnesmembrespubliques first et second .
Exemple1417.Utilisationdespaires
#include <iostream>
#include <utility>
usingnamespacestd;
intmain(void)
{
//Construitunepaireassociantunentier
//unflottant:
pair<int,double> p1(5,7.38),p2;
//Initialisep2avecmake_pair:
p2=make_pair(9,3.14);
//Affichelesdeuxpaires:
cout << "p1=(" << p1.first << ","
<< p1.second << ")" << endl;
cout << "p2=(" << p2.first << ","
<< p2.second << ")" << endl;
return0;
}

Laclasse template pairdisposegalementdoprateursdecomparaisonquiutilisentlordrelexico


graphiqueinduitparlesvaleursdesesdeuxlments.Deuxpairessontdoncgalessietseulement
sileurscouplesdevaleurssontgauxmembremembre, etunepaireestinfrieurelautresila
premirevaleurdelapremirepaireestinfrieurelavaleurcorrespondantedeladeuximepaire,
ou,siellessontgales,ladeuximevaleurdelapremirepaireestinfrieureladeuximevaleurde
ladeuximepaire.

256

Chapitre14.Lestypescomplmentaires

14.3.Lestypesnumriques
Enplusdestypesdintrtgnralvusdanslessectionsprcdentes,labibliothquestandardfournit
destypesdedonnesplusspcialissdanslescalculsnumriquesoumathmatiques.Cestypesde
donnespermettentdeffectuerdescalculssurlesnombrescomplexes,ainsiquedescalculsparallles
surdestableauxdevaleurs.

14.3.1.Lescomplexes
LestypesdebasedulangageC++fournissentuneapproximationrelativementfiabledesdiffrents
domainesdenombresmathmatiques. Parexemple, letypeintpermetdereprsenteruneplagede
valeurslimitedesentiersrelatifs, maissuffisammentlargetoutefoispourpermettredeffectuerla
plupart descalculsintervenant danslavierelle. Demme, lestypesdesnombresvirguleflot
tantefournissentuneapproximationrelativementsatisfaisantedesnombresrelsdesmathmatiques.
Lapproximationcettefoisportenonseulementsurlaplagedevaleuraccessible,maisgalementsur
laprcisiondesnombres.
Note:Onprendrabienconsciencedufaitquelestypesdulangagenereprsententeffective
mentquedesapproximations,carlesordinateurssontdesmachineslimitesenmmoireeten
capacitdereprsentationdumonderel. Il faut donctoujourspenserauxventuelscasde
dbordementseterreursdereprsentationdesnombres,surtoutencequi concernelesnom
bresrels.Lesbogueslesplusgraves(entermedepertesmatriellesouhumaines)sontsouvent
dsdetelsdbordements,quisontinhrentsauxtechniquesutilisesparlinformatique(mme
avecdeslangagesplussrsqueleC++).

Ilexisteenmathmatiquesunautretypedenombres,quinontpasdereprsentationphysiqueim
mdiatepourlecommundesmortels, maisquipermettentsouventdesimplifierbeaucoupcertains
calculs:lesnombrescomplexes.Cesnombrestendenteneffetledomainedesnombresaccessibles
etpermettentdepoursuivrelescalculsquintaientpasralisablesaveclesnombresrelsseulement,
ensaffranchissantdescontraintesimposessurlessolutionsdesquationsalgbriques.Lesnombres
complexessontdoncdunetrsgrandeutilitdanstoutelalgbre,etenparticulierdanslescalculs
matricielsoilsprennentuneplaceprdominante.Lesnombrescomplexespermettentgalementde
simplifiersrieusementlescalculstrigonomtriques,lescalculsdesignauxenlectricitetlescal
culsenmcaniquequantique.Leplusintressantaveccesnombresestsansdoutelefaitquemme
silesrsultatsintermdiairesquelontrouveaveceuxnontpasdesignificationrelle,lesrsultats
finaux,eux,peuventenavoiruneetnauraientpasttrouvsaussifacilementenconservanttoutes
lescontraintesimposesparlesnombresrels.
Afindesimplifierlaviedesprogrammeursqui ont besoindemanipulerdesnombrescomplexes,
labibliothquestandardC++dfinitlaclasse template complex,quipermetdelesreprsenteret
deffectuerlesprincipalesoprationsmathmatiquesdessus.Silutilisationdelaclassecomplexen
soi neposeaucunproblmeparticulier, il peut treutilededonnerunedescriptionsommairede
cequest unnombrecomplexepourlesnophytesenmathmatiques.
Toutefois, cettedescription
nestpasdestineauxpersonnesnayantaucuneconnaissanceenmathmatiques(sitantestquun
programmeurpuissetredanscecas...). Si vousnelacomprenezpas, cest sansdoutequevous
navezaucunement besoindesnombrescomplexeset vouspouvezdoncpassercettesectionsans
crainte.

257

Chapitre14.Lestypescomplmentaires

14.3.1.1.Dfinitionetprincipalespropritsdesnombrescomplexes
Ilnestpascompliqudesereprsentercequesignifieunnombrerelpuisquonlesutilisecouram
mentdanslaviecourante. Lamthodelaplussimpleestdimaginerunerglegradueochaque
positionestdonneparunnombrerelparrapportlorigine.Cenombreindiquelenombredefois
quelunitdedistancedoittrerptedepuisloriginepourarrivercetteposition.
Poursereprsenterlavaleurdunnombrecomplexe,ilfaututiliserunedimensionsupplmentaire.
Enfait,toutnombrecomplexepeuttreexprimavecdeuxvaleursrelles:lapartierelleducom
plexe,etsapartieimaginaire.Plusieursnotationsexistentpourreprsenterlesnombrescomplexes
partirdecesdeuxparties.Lapluscouranteestdedonnerlapartierelleetlapartieimaginaireentre
parenthses,sparesparunevirgule:
(relle,imaginaire)

o relle estlavaleurdelapartierelle,et imaginaire lavaleurdelapartieimaginaire. Ilest


galementtrscourantenFrancedenoterlesdeuxpartiesdirectementenlessparantdunsigne
dadditionetenaccolantlecaractre i(pourimaginaire)lapartieimaginaire:
relle+imaginairei

Lexemplesuivantvousprsentequelquesnombrescomplexes:
7.56
3i
5+7i

Vousconstaterezquelesnombresrelspeuventparfaitementtrereprsentsparlesnombrescom
plexes,puisquilsuffitsimplementdutiliserunepartieimaginairenulle.
Lesoprationsalgbriquesclassiquesonttdfiniessurlesnombrescomplexes. Lesadditionset
soustractionssefontmembremembre,partierelleavecpartierelleetpartieimaginaireavecpartie
imaginaire.Enrevanche,lamultiplicationestunpeupluscomplexe,carellesebasesurlaproprit
fondamentalequelecarrdelunitdelapartieimaginairevaut 1.Autrementdit,lesymbole i de
i2 =1. Ilsagitenquelque
lanotationprcdentedisposedelapropritfondamentalesuivante:
sorteduneracinecarrede 1 (laracinecarredesnombresngatifsnayantpasdesens,puisquun
carrestnormalementtoujourspositif, oncomprendlaqualificationdimaginairedesnombres
complexes).partirdecettergledebase,etenconservantlesrglesdassociativitdesoprateurs,
onpeutdfinirleproduitdedeuxnombrescomplexescommesuit:
(a,b)*(c,d)=(acbd,ad+bc)

Enfin, ladivisionsedfinit toujourscommeloprationinversedelamultiplication, cestdire


loprationquitrouvelenombrequi,multipliparlediviseur,redonneledividende.Chaquenombre
complexenonnuldisposeduninverse,quiestlersultatdeladivisionde 1 parcenombre.Onpeut
montrerfacilementquelinversedunnombrecomplexeestdfinicommesuit:
1/(a,b)=(a/(a2 +b

),b/(a2 +b

))

partirdelinverse,ilestsimpledecalculerunedivisionquelconque.
Commeillatditplushaut,lesnombrescomplexespeuventtrereprsentsenutilisantunedimen
sionsupplmentaire.Ainsi,siondfinitunrepredansleplan,dontlaxedesabscissesestassoci
lapartierelledesnombrescomplexesetlaxedesordonneslapartieimaginaire,toutnombre
complexeestassociunpointduplan.Onappellealorsceplanleplancomplexe.Ladfinitiondes
complexesdonneicicorresponddoncunsystmedecoordonnescartsiennesduplancomplexe,
etchaquenombrecomplexedisposedesesproprescoordonnes.

258

Chapitre14.Lestypescomplmentaires
Enmathmatiques,ilestgalementcourantdutiliserunautresystmedecoordonnes:lesystme
decoordonnespolaires.Danscesystme,chaquepointduplanestidentifinonplusparlescoor
donnesdesesprojectionsorthogonalessurlesaxesdurepre,maisparsadistancelorigineetpar
langlequeladroitequirejointlorigineaupointfaitaveclaxedesabscisses.Cesdeuxnombressont
courammentnotsrespectivementavecleslettresgrecquesrhoettheta.Ladnominationdecoordon
nespolairesprovientdufaitqueloriginedureprejouelerledunpleparrapportauquelonsitue
lepointdansleplan.
Ilestdoncvidentquelesnombrescomplexespeuventgalementtrereprsentsparleurscoor
donnespolaires.Onappellegnralementladistanceloriginelanormedunombrecomplexe,et
langlequilfaitaveclaxedesabscissessonargument.Faitesbienattentionceterme,ilnerepr
sentepasunargumentdunefonctionouquoiquecesoitquiserapportelaprogrammation.
Laplupartdesfonctionsmathmatiquesclassiquesonttdfiniessurlesnombrescomplexes,par
foisenrestreignantleurdomainedevalidit.Ainsi,ilestpossibledecalculerunsinus,uncosinus,
uneexponentielle,etc.pourlesnombrescomplexes.Ilestbienentenduhorsdequestiondedfinir
rigoureusement,nimmedeprsentersuccinctementcesfonctionsdanscedocument.Cependant,il
estbondesavoirquonnepeutpasdfinirunerelationdordresurlesnombrescomplexes.Autrement
dit,onnepeutpasfairedautrecomparaisonquelgalitentredeuxnombrescomplexes(essayezde
comparerlesnombrescomplexessitussuruncerclecentrloriginedansleplancomplexepour
vousenrendrecompte).

14.3.1.2.Laclassecomplex
Laclasse template complexestdfiniedanslentte complex delabibliothquestandard.Cette
classepeut treinstanciepourlunquelconquedestroistypesdenombrevirguleflottantedu
langage:float,doubleoulongdouble.Ellepermetdeffectuerlesprincipalesoprationsdfiniessur
lesnombrescomplexes,commelesadditions,soustractions,multiplications,division,maisgalement
desoprationsspcifiquesauxnombrescomplexes,commeladterminationdeleurargumentoude
leurnorme.Enfin,lentte complex contientdessurchargesdesfonctionsmathmatiquesstandards,
tellesquelesfonctionstrigonomtriques,laracinecarre,lespuissancesetexponentielles,ainsique
leslogarithmes(dfinissurleplancomplexeauquellaxedesabscissesngativesatt).
Laconstructionduncomplexeneposeaucunproblmeensoi.
Laclassecomplexdisposedun
constructeurpardfaut,dunconstructeurdecopieetdunconstructeurprenantenparamtrelapartie
relleetlapartieimaginairedunombre:
#include <iostream>
#include <complex>
usingnamespacestd;
intmain(void)
{
complex<double> c(2,3);
cout << c << endl;
return0;
}

Lexempleprcdentprsentegalementloprateurdesortiesurlesfluxstandards,quiformateun
nombrecomplexeenutilisantlanotation (rel,imaginaire).Ilexistegalementunesurcharge
deloprateurdentrepourlefluxdentre:

259

Chapitre14.Lestypescomplmentaires
#include <iostream>
#include <complex>
usingnamespacestd;
intmain(void)
{
complex<double> c;
cin >> c;
cout << "Vousavezsaisi:"
return0;
}

<< c << endl;

Note:Malheureusement,cettenotationposedesproblmesaveclalocalefranaise,puisque
nousutilisonsdesvirgulespoursparerlapartieentiredelapartiedcimaledesnombres
virgules.Lorsquelundesdeuxnombresflottantsestunentier,il estimpossiblededterminer
osetrouvelavirgulesparant lapartieentiredelapartieimaginairedunombrecomplexe.
Unepremiresolutionestdemodifierleformatagedesnombresrelspourqueleschiffresaprs
lavirgulesoient toujoursaffichs, mmesilssont nuls. Cependant, il faut galement imposer
quelessaisiesdesnombressoientgalementtoujourseffectusavecdesnombresvirgules,
cequi estsujeterreuretinvrifiable.Il estdoncrecommanddenutiliserquelalocaledela
bibliothqueClorsquonfaitunprogrammeutilisantlesnombrescomplexes.

Ilnexistepasdeconstructeurpermettantdecrerunnombrecomplexepartirdesescoordonnes
polaires. Enrevanche, lafonction polar permetdenconstruireun. Cettefonctionprendenpara
mtrelanormeducomplexeconstruireainsiquesonargument.Ellerenvoielenombrecomplexe
nouvellementconstruit.
Lapartieimaginaireetlapartierelledunnombrecomplexepeuventtrercuprestoutinstant
laidedesmthodes real et imag delaclasse template complex.Ilestgalementpossibledutiliser
lesfonctions templaterealet imag,quiprennenttoutesdeuxlenombrecomplexedontilfautcal
culerlapartierelleetlapartieimaginaire.Demme,lanormedunnombrecomplexeestretourne
parlafonction abs,etsonargumentpeuttreobtenuaveclafonction arg.
Bienentendu,lesoprationsclassiquessurlescomplexessefontdirectement,commesilsagissait
duntypeprdfinidulangage:
#include <iostream>
#include <complex>
usingnamespacestd;
intmain(void)
{
complex<double> c1(2.23,3.56);
complex<double> c2(5,5);
complex<double> c=c1+c2;
c=c/(c1c2);
cout << c << endl;
return0;
}

260

Chapitre14.Lestypescomplmentaires
Lesfonctionsspcifiquespermettantdemanipulerlescomplexesetdeleurappliquerlesoprations
quileurssontpropressontrcapitulesdansletableausuivant:
Tableau142.Fonctionsspcifiquesauxcomplexes
Fonction

Description

real

Retournelapartierelledunombrecomplexe.

imag

Retournelapartieimaginairedunombrecomplexe.

abs

Retournelanormedunombrenombrecomplexe,cestdiresadistance
lorigine.

arg

Retournelargumentdunombrecomplexe.

norm

Retournelecarrdelanormedunombrecomplexe.Attention,cette
fonctionportemalsonnom,puisquelavraienormeestretourneparla
surchargedelafonction abs pourlesnombrescomplexes.Cette
incohrenceprovientdelinterprtationdiffrentedecelledesFranais
quefontlesAnglosaxonsdelanotiondenorme.

conj

Retournelenombrecomplexeconjugudunombrecomplexefournien
argument.Lenombreconjugudunnombrecomplexeestsonsymtrique
parrapportlaxedesabscissesdansleplancomplexe,cestdirequil
disposedelammepartierelle,maisquesapartieimaginaireest
opposecelledunombrecomplexeoriginal(celarevientgalement
direquelargumentduconjuguestlopposdelargumentducomplexe
original).Leproduitdunnombrecomplexeetdesonconjugudonnele
carrdesanorme.

polar

Permetdeconstruireunnombrecomplexepartirdesescoordonnes
polaires.

Exemple1418.Manipulationdesnombrescomplexes
#include <iostream>
#include <complex>
usingnamespacestd;
intmain(void)
{
//Creunnombrecomplexe:
complex<double> c(2,3);
//Dterminesonargumentetsanorme:
doubleArg=arg(c);
doubleNorm=abs(c);
//Construitlenombrecomplexeconjugu:
complex<double> co=polar(Norm,Arg);
//Affichelecarrdelanormeduconjugu:
cout << norm(co) << endl;
//Calculelecarrcecettenormeparleproduit
//ducomplexeetdesonconjugu:
cout << real(c*conj(c)) << endl;
return0;
}

261

Chapitre14.Lestypescomplmentaires

14.3.2.Lestableauxdevaleurs
CommeillatexpliqudansleChapitre1,lesprogrammesclassiquesfonctionnenttoujourssurle
mmeprincipe:ilstravaillentsurdesdonnesquilsreoiventenentreetproduisentdesrsultatsen
sortie.Cemodedefonctionnementconvientdanslagrandemajoritdescas,etenfaitlesprogrammes
quelonappellecourammentlesfiltresensontunedesapplicationsprincipales.Unfiltrenest
riendautrequunprogrammepermettant,commesonnomlindique,defiltrerlesdonnesreuesen
entreselonuncritreparticulieretdenefournirensortiequelesdonnesquisatisfontcecritre.
Certainsfiltresplusvoluspeuventmmemodifierlesdonneslavoleoulestraduiredansun
autreformat. Lesfiltressonttrssouventutilissaveclesmcanismesderedirectiondessystmes
quilessupportentafindexcuterdestraitementscomplexessurlesfluxdedonnespartirdefiltres
simples,eninjectantlesrsultatsdesunsdanslefluxdentredesautres.
Cependant,cemodleaunelimitepratiqueentermedeperformances,carilncessiteuntraitement
squentiel desdonnes. Lavitessedexcutiondunprogrammeconuseloncemodleest
donc
directementlilavitessedexcutiondesinstructions,donclavitesseduprocesseurdelamachine
utilise.Lorsquunhautniveaudeperformancedoittreatteint,plusieurssolutionssontdisponibles.
Danslapratique,ondistinguetroissolutionsclassiques.
Lapremiresolutionconsistesimplement,pouraugmenterlapuissancedunemachine,augmenter
celleduprocesseur.Celasetraduitsouventparuneaugmentationdelafrquencedeceprocesseur,
techniquequetoutlemondeconnat. Lesavantagesdecettesolutionsontvidents:touslespro
grammesbnficientdirectementdelaugmentationdelapuissanceduprocesseuretnontpastre
modifis.Enrevanche,cettetechniqueatteindraunjourouunautreseslimitesentermesdecotsde
fabricationetdemoyenstechniquesmettreenoeuvrepourproduirelesprocesseurs.
Ladeuximesolutionestdaugmenterlenombredeprocesseursdelamachine.Cettesolutionesttrs
simple,maissupposequelesprogrammessoientcapablesdeffectuerplusieurscalculsindpendants
simultanment.Enparticulier,lestraitementseffectuerdoiventtresuffisammentindpendantset
nepasavoirattendrelesdonnesproduitesparlesautresafindepouvoirrellementtreex
cutsenparallle. Onquittedonclemodlesquentiel, pourentrerdansunmodledetraitement
ochaqueprocesseurtravailleenparallle(modleMIMD,abrviationdelanglaisMultiple
InstructionMultipleData).Cettetechniqueestgalementsouventappeleleparalllismedetraite
ment.Malheureusement,pourununiqueprocessuspurementsquentiel,cettetechniqueneconvient
pas,puisquedetoutesfaons,lesoprationsexcuterneleserontqueparunseulprocesseur.
Enfin,ilexisteunetechniquemixte,quiconsisteparallliserlesdonnes.Lesmmesoprationsdun
programmesquentielsontalorsexcutessurungrandnombrededonnessimilaires.Lesdonnes
sontdonctraitesparblocs,parununiquealgorithme:ilsagitduparalllismededonnes(SIMD
enanglais,abrviationdeSingleInstructionMultipleData).Cettesolutionestcellemiseenoeuvre
danslesprocesseursmodernesquidisposentdejeuxdinstructionsspcialisespermettantdeffectuer
descalculssurplusieursdonnessimultanment (MMX, 3DNowet SSEpourlesprocesseursde
typex86parexemple).Bienentendu,cettetechniquesupposequeleprogrammeaiteffectivement
traiterdesdonnessemblablesdemaniresimilaire. Cettecontraintepeutparatretrsforte, mais,
enpratique,lessituationslesplusconsommatricesderessourcessontjustementcellesquincessite
larptitiondunmmecalcul surplusieursdonnes. Onciteraparexempletouslesalgorithmes
detraitementdedonnesmultimdia,dontlesalgorithmesdecompression,detransformationetde
combinaison.
Silaugmentationdesperformancesdesprocesseursapporteungaindirectementobservablesurtous
lesprogrammes, cenestpaslecaspourlestechniquesdeparalllisation. Leparalllismedetrai
tement est gnralement accessibleauniveausystme, parlintermdiairedumultitcheet dela
programmationmultithreade. Il faut donccrirelesprogrammesdetellesortebnficierdece
paralllismedetraitement,laidedesfonctionsspcifiqueausystmedexploitation.Demme,le
paralllismededonnesncessiteladfinitiondetypesdedonnescomplexes,capablesdereprsen

262

Chapitre14.Lestypescomplmentaires
terlesblocsdedonnessurlesquelsleprogrammedoittravailler.
Cesblocsdedonnessontcou
rammentgrscommedesvecteursoudesmatrices,cestdire,engnral,commedestableauxde
nombres.Leprogrammedoitdoncutilisercestypesspcifiquespouraccdertouteslesressources
delamachine.Celancessiteunsupportdelapartdulangagedeprogrammation.
Chaqueenvironnementdedveloppementestsusceptibledefournirlestypesdedonnespermettant
deffectuerdestraitementsSIMD.Cependant,cestypesdpendentdelenvironnementutiliseten
coreplusdelaplateformeutilise.LabibliothquestandardC++permetdvitercescueils,carelle
dfinituntypededonnepermettantdetraiterdestableauxunidimensionnelsdobjets,enassurant
quelesmcanismesdoptimisationpropreauxplatesformesmatriellesetauxcompilateursseront
effectivementutiliss:lesvalarray.

14.3.2.1.Fonctionnalitsdebasedesvalarray
Laclassevalarrayestuneclasse template capabledestockeruntableaudevaleursdesontype
template.Ilestpossibledelinstancierpourtouslestypesdedonnespourlesquelslesoprations
dfiniessurlaclassevalarraysontellesmmesdfinies.LabibliothquestandardC++garantitque
laclassevalarrayestcritedetellesortequetouslesmcanismesdoptimisationdescompilateurs
pourronttreappliqussurelle,afindobtenirdesperformancesoptimales.Deplus,chaqueimpl
mentationestlibredutiliserlespossibilitsdecalculparallledisponiblesurchaqueplateforme,du
moinspourlestypespourlesquelscesfonctionnalitssontprsentes.Parexemple,laclassevalarray
instanciepourletypefloatpeututiliserlesinstructionsspcifiquesdecalculsurlesnombresflottants
duprocesseursiellessontdisponibles.Toutefois,lanormenimposeaucunecontrainteceniveau,
etlamaniredontlaclassevalarrayestimplmenteresteladiscrtiondechaquefournisseur.
Laclassevalarrayfournit touteslesfonctionnalitsncessaireslaconstructiondestableauxde
valeurs,leurinitialisation,ainsiquleurmanipulation.Elleestdclarecommesuitdanslentte
valarray :
//Dclarationdesclassesdeslectiondesoustableau:
classslice;
classgslice;
//Dclarationdelaclassevalarray:
template <classT >
classvalarray
{
public:
//Typesdesdonnes:
typedefTvalue_type;
//Constructeursetdestructeurs:
valarray();
explicitvalarray(size_ttaille);
valarray(constT&valeur,size_ttaille);
valarray(constT*tableau,size_ttaille);
valarray(constvalarray&source);
valarray(constmask_array
<T> &source);
valarray(constindirect_array
<T> &source);
valarray(constslice_array
<T> &source);
valarray(constgslice_array
<T> &source);
~valarray();
//Oprateursdaffectation:
valarray<T> &operator=(constT&valeur);
valarray<T> &operator=(constvalarray
<T> &source);

263

Chapitre14.Lestypescomplmentaires
valarray<T>
valarray<T>
valarray<T>
valarray<T>

&operator=(constmask_array
<T> &source);
&operator=(constindirect_array
<T> &source);
&operator=(constslice_array
<T> &source);
&operator=(constgslice_array
<T> &source);

//Oprateursdaccsauxlments:
Toperator[](size_tindice)const;
T&operator[](size_tindice);
//Oprateursdeslectiondesousensembledutableau:
valarray<T>
operator[](constvalarray<bool> &masque)const;
mask_array<T>
operator[](constvalarray<bool> &masque);
valarray<T>
operator[](constvalarray<size_t> &indices)const;
indirect_array<T> operator[](constvalarray
<size_t> &indices);
valarray<T>
operator[](sliceselecteur)const;
slice_array<T>
operator[](sliceselecteur);
valarray<T>
operator[](constgslice&selecteur)const;
gslice_array<T>
operator[](constgslice&selecteur);
//Oprateursunaires:
valarray<T> operator+()const;
valarray<T> operator()const;
valarray<T> operator~()const;
valarray<T> operator!()const;
//Oprateursdaffectationcompose:
valarray<T> operator*=(constT&valeur);
valarray<T> operator*=(constvalaray
<T> &tableau);
valarray<T> operator/=(constT&valeur);
valarray<T> operator/=(constvalaray
<T> &tableau);
valarray<T> operator%=(constT&valeur);
valarray<T> operator%=(constvalaray
<T> &tableau);
valarray<T> operator+=(constT&valeur);
valarray<T> operator+=(constvalaray
<T> &tableau);
valarray<T> operator=(constT&valeur);
valarray<T> operator=(constvalaray
<T> &tableau);
valarray<T> operator^=(constT&valeur);
valarray<T> operator^=(constvalaray
<T> &tableau);
valarray<T> operator&=(constT&valeur);
valarray<T> operator&=(constvalaray
<T> &tableau);
valarray<T> operator|=(constT&valeur);
valarray<T> operator|=(constvalaray
<T> &tableau);
valarray<T> operator<<=(constT&valeur);
valarray<T> operator<<=(constvalaray<T> &tableau);
valarray<T> operator>>=(constT&valeur);
valarray<T> operator>>=(constvalaray<T> &tableau);
//Oprationsspcifiques:
size_tsize()const;
Tsum()const;
Tmin()const;
Tmax()const;
valarray<T> shift(int)const;
valarray<T> cshift(int)const;
valarray<T> apply(Tfonction(T))const;
valarray<T> apply(Tfonction(constT&))const;
voidresize(size_ttaille,Tinitial=T());

264

Chapitre14.Lestypescomplmentaires
};

Nousverronsdanslasectionsuivantelasignificationdestypesslice,gslice,slice_array,gslice_array,
mask_arrayetindirect_array.
Ilexisteplusieursconstructeurspermettantdecreretdinitialiseruntableaudevaleurs.Leconstruc
teurpardfautinitialiseuntableaudevaleurvide. Lesautresconstructeurspermettentdinitialiser
letableaudevaleurpartirdunevaleurdinitialisationpourtousleslmentsduvalarray,oudun
autretableaucontenantlesdonnesaffecterauxlmentsduvalarray:
//Construitunvalarraydedoubles:
valarray<double> v1;
//Initialiseunvalarraydedoublesexplicitement:
doublevaleurs[]={1.2,3.14,2.78,1.414,1.732};
valarray<double> v2(valeurs,
sizeof(valeurs)/sizeof(double));
//Construitunvalarrayde10entiersinitialiss3:
valarray<int> v3(3,10);

Vouspouvezconstaterqueledeuximeargumentdesconstructeursquipermettentdinitialiserles
valarrayprennentunargumentdetypesize_t,quiindiquelatailleduvalarray.Unefoisunvalarray
construit,ilestpossibledeleredimensionnerlaidedelamthode resize.Cettemthodeprenden
premierparamtrelanouvelletailleduvalarrayetlavaleuraffecterauxnouveauxlmentsdansle
casdunagrandissement.Lavaleurpardfautestcellefournieparleconstructeurpardfautdutype
desdonnescontenuesdanslevalarray. Lataillecourantedunvalarraypeuttrercupretout
momentgrcelamthode size.
Exemple1419.Modificationdelatailledunvalarray
#include <iostream>
#include <valarray>
usingnamespacestd;
intmain(void)
{
//Crationdunvalarray:
valarray<double> v;
cout << v.size() << endl;
//Redimensionnementduvalarray:
v.resize(5,3.14);
cout << v.size() << endl;
return0;
}

Touteslesoprationsclassiquesdesmathmatiquespeuventtreappliquessurunvalarraypourvu
quellespuissentltregalementsurletypedesdonnescontenuesparcetableau.Ladfinitionde
cesoprationsesttrssimple:loprationdutypedebaseestappliquesimplementchaquelment
contenudansletableaudevaleurs.

265

Chapitre14.Lestypescomplmentaires
Labibliothquestandarddfinitgalementlesoprateursbinairesncessairespoureffectuerlesop
rationsbinairessurchaquelmentdesvalarray.Enfait,cesoprateurssontclasssendeuxcatgo
ries,selonlanaturedeleursarguments.Lesoprateursdelapremirecatgoriepermettentdeffectuer
uneoprationentredeuxvalarraydemmedimension,
enappliquant cetteoprationmembre
membre. Ilsagitdoncrellementduneoprationvectorielledanscecas.
Enrevanche, lesopra
teursdeladeuximecatgorieappliquentloprationavecunemmeetuniquevaleurpourchaque
donnestockedanslevalarray.
Exemple1420.Oprationssurlesvalarray
#include <iostream>
#include <valarray>
usingnamespacestd;
voidaffiche(constvalarray
<double> &v)
{
size_ti;
for(i=0;i <v.size();++i)
cout << v[i] << "";
cout << endl;
}
intmain(void)
{
//Construitdeuxvalarraydedoubles:
doublev1[]={1.1,2.2,3.3};
doublev2[]={5.3,4.4,3.5};
valarray<double> vect1(v1,3);
valarray<double> vect2(v2,3);
valarray<double> res(3);
//Effectueunesommemembremembre:
res=vect1+vect2;
affiche(res);
//Calculelesinusdesmembresdupremiervalarray:
res=sin(vect1);
affiche(res);
return0;
}

Parmilesoprateursbinairesquelonpeutappliquerunvalarray,ontrouvebienentendulesop
rateursdecomparaison.Cesoprateurs,contrairementauxoprateursdecomparaisonhabituels,ne
renvoientpasunboolen,maispluttunautretableaudeboolens.Eneffet,lacomparaisondedeux
valarrayapourrsultat levalarraydesrsultatsdescomparaisonsmembresmembresdesdeux
valarray.
Laclassevalarraydisposedemthodespermettantdeffectuerdiversesoprationsspcifiquesaux
tableauxdevaleurs.Lamthode sum permetdobtenirlasommedetouteslesvaleursstockesdansle
tableaudevaleur.Lesmthodesshift et cshift permettent,quantelles,deconstruireunnouveau
valarraydontleslmentssontleslmentsduvalarrayauquellamthodeestapplique,dcalsou
permutscirculairement duncertainnombredepositions. Lenombrededplacementseffectus
estpassenparamtrecesdeuxfonctions, lesvaleurspositivesentranantdesdplacementsvers
lagaucheet lesvaleursngativesdesdplacementsversladroite. Danslecasdesdcalagesles
nouveauxlmentsintroduitspourremplacerceuxquinontpaseuxmmesderemplaantprennent
lavaleurspcifieparleconstructeurpardfautdutypeutilis.

266

Chapitre14.Lestypescomplmentaires
Exemple1421.Dcalagesetrotationsdevaleurs
#include <iostream>
#include <valarray>
usingnamespacestd;
voidaffiche(constvalarray
<double> &v)
{
size_ti;
for(i=0;i <v.size();++i)
cout << v[i] << "";
cout << endl;
}
intmain(void)
{
//Construitunvalarraydedoubles:
doublev1[]={1.1,2.2,3.3,4.4,5.5};
valarray<double> vect1(v1,5);
valarray<double> res(5);
//Effectueundcalagegauchededeuxpositions:
res=vect1.shift(2);
affiche(res);
//Effectueunerotationde2positionsversladroite:
res=vect1.cshift(2);
affiche(res);
return0;
}

Enfin, ilexistedeuxmthodes apply permettantdappliquerunefonctionchaquelmentdun


valarrayet deconstruireunnouveauvalarraydemmetailleet contenant lesrsultats. Cesdeux
surchargespeuventtravaillerrespectivementavecdesfonctionsprenantenparamtresoitparvaleur,
soitparrfrence,lobjetsurlequelellesdoiventtreappliques.

14.3.2.2.Slectionmultipledeslmentsdunvalarray
Leslmentsdunvalarraypeuvent treaccdslaidedeloprateurdaccsauxlmentsde
tableau [].Lafonction affiche desexemplesduparagrapheprcdentutilisecettefonctionnalit
pourenrcuprerlavaleur.Cependant,lesvalarraydisposedemcanismesplussophistiquspour
manipulerleslmentsdestableauxdevaleurengroupe,afindebnficierdetouslesmcanismes
doptimisationquipeuventexistersuruneplateformedonne.Grcecesmcanismes,ilestpossible
deffectuerdesoprationssurdespartiesseulementdunvalarrayoudcriredenouvellesvaleurs
danscertainsdeseslmentsseulement.
Poureffectuercesslectionsmultiples,plusieurstechniquessontdisponibles.Cependant,toutesces
techniquessebasentsurlemmeprincipe,puisquellespermettentdefiltrerleslmentsduvalarray
pournenslectionnerquunepartieseulement.Lersultatdecefiltragepeuttreunnouveauvalarray
ouuneautreclassepouvanttremanipuleexactementdelammemanirequunvalarray.
Enpratique,ilexistequatremaniresdeslectionnerdeslmentsdansuntableau.Nousallonsles
dtaillerdanslessectionssuivantes.

267

Chapitre14.Lestypescomplmentaires
14.3.2.2.1. Slection par un masque
Lamanirelaplussimpleestdutiliserunmasquedeboolensindiquantquelslmentsdoiventtre
slectionnsounon.Lemasquedeboolensdoitobligatoirementtreunvalarraydemmedimension
quelevalarraycontenantleslmentsslectionner.Chaquelmentestdoncslectionnenfonction
delavaleurduboolencorrespondantdanslemasque.
Unefoislemasqueconstruit,laslectiondeslmentspeuttreralisesimplementenfournissant
cemasqueloprateur [] duvalarraycontenantleslmentsslectionner.
Lavaleurretourne
template mask_array, parlintermdiairede
parcetoprateurestalorsuneinstancedelaclasse
laquelleleslmentsslectionnspeuventtremanipuls.Pourlesvalarrayconstantscependant,la
valeurretourneestunautrevalarray,contenantunecopiedeslmentsslectionns.
Laclassemask_arrayfournitunnombrelimitdoprations. Enfait, sesinstancesnedoiventtre
utilisesquepoureffectuerdesoprationssimplessurleslmentsdutableauslectionnparle
masquefourniloprateur [].LesoprationsralisablesserontdcritesdanslaSection14.3.2.2.4.
Laslectiondeslmentsduntableauparlintermdiairedunmasqueestutilisecourammentavec
lesoprateursdecomparaisondesvalarray,puisqueceuxcirenvoientjustementuntelmasque.Ilest
donctrsfaciledeffectuerdesoprationssurleslmentsdunvalarrayquivrifientunecertaine
condition.
Exemple1422.Slectiondeslmentsdunvalarrayparunmasque
#include <iostream>
#include <valarray>
usingnamespacestd;
voidaffiche(constvalarray
<int> &v)
{
size_ti;
for(i=0;i <v.size();++i)
cout << v[i] << "";
cout << endl;
}
intmain(void)
{
//Construitunvalarraydentier:
intvaleurs[]={1,5,9,4,3,7,21,32};
valarray<int> vi(valeurs,
sizeof(valeurs)/sizeof(int));
affiche(vi);
//Multipliepar2touslesmultiplesde3:
vi[(vi%3)==0]*=valarray
<int>(2,vi.size());
affiche(vi);
return0;
}

14.3.2.2.2. Slection par indexation explicite


Laslectiondeslmentsdunvalarrayparunmasquedeboolensestexpliciteetfacileutiliser,
maisellesouffredeplusieursdfauts.Premirement,ilfautfourniruntableaudeboolendemme
dimensionquelevalarraysource.Autrementdit,ilfautfournirunevaleurboolennepourtousles

268

Chapitre14.Lestypescomplmentaires
lmentsdutableau,mmepourceuxquinenousintressentpas.Ensuite,leslmentsslectionns
apparaissentsystmatiquementdanslemmeordrequeceluiquilsontdanslevalarraysource.
LabibliothquestandardC++fournitdoncunautremcanismedeslection,toujoursexplicite,mais
quipermetdefaireunerindexationdeslmentsainsislectionns.Cettefois,ilnefautplusfournir
unmasqueloprateur [],maisunvalarraycontenantdirectementlesindicesdeslmentsslec
tionns. Cesindicespeuvent nepastredanslordrecroissant, cequi permet doncderarranger
lordredeslmentsainsislectionns.
Exemple1423.Slectiondeslmentsdunvalarrayparindexation
#include <iostream>
#include <valarray>
usingnamespacestd;
voidaffiche(constvalarray
<int> &v)
{
size_ti;
for(i=0;i <v.size();++i)
cout << v[i] << "";
cout << endl;
}
intmain(void)
{
//Construitunvalarraydentier:
intvaleurs[]={1,5,9,4,3,7,21,32};
valarray<int> vi(valeurs,
sizeof(valeurs)/sizeof(int));
affiche(vi);
//Multipliepar2leslmentsdindices2,5et7:
size_tindices[]={2,5,7};
valarray<size_t> ind(indices,
sizeof(indices)/sizeof(size_t));
vi[ind]*=valarray<int>(2,ind.size());
affiche(vi);
return0;
}

Lavaleurretourneparloprateurdeslectionsurlesvalarraynonconstantsestcettefoisdutype
indirect_array. Commepourlaclassemask_array, lesoprationsralisablesparlintermdiairede
cetteclassesontlimitesetdoiventserviruniquementmodifierleslmentsslectionnsdansle
valarraysource.

14.3.2.2.3. Slection par indexation implicite


Dansbeaucoupdesituations,lesindicesdeslmentsslectionnssuiventunmotifrgulieretilnest
pastoujourspratiquedespcifiercemotifexplicitement.Lamthodedeslectionprcdentenest
danscecaspastrspratiqueetilestalorsprfrabledeslectionnerleslmentsparunjeudindices
dcritsdemanireimplicite.Labibliothquefournitceteffetdeuxclassesutilitairespermettantde
dcriredesjeuxdindicesplusoumoinscomplexes:laclassesliceetlaclassegslice.
Cesdeuxclassesdfinissentlesindicesdeslmentsslectionnerlaidedeplusieursvariables
pouvantprendreuncertainnombredevaleursespacesparunpasdincrmentationfixe.Ladfinition
desindicesconsistedoncsimplementdonnerlavaleurdedpartdelindicedeslection,lenombre

269

Chapitre14.Lestypescomplmentaires
devaleursgnrerpourchaquevariableetlepasquisparecesvaleurs.Lesvariablesdecontrle
commencenttoutesleuritrationpartirdelavaleurnulleetprennentcommevaleurssuccessivesles
multiplesdupasquellesutilisent.
Note:Enralit,laclassesliceestuncasparticulierdelaclassegslicequinutilisequuneseule
variabledecontrlepourdfinirlesindices.Lesslicenesontdoncriendautrequedesgslice
unidimensionnels.
LetermedegsliceprovientdelanglaisGeneralizedSlice,quisignifiebienquelesgslicesont
desslicetenduesplusieursdimensions.

Laclassesliceest relativement facileutiliser, puisquil suffit despcifierlavaleurdedpart de


lindice,lenombredevaleursgnreretlepasquidoitlessparer.Elleestdclarecommesuit
danslentte valarray :
classslice
{
public:
slice();
slice(size_tdebut,size_tnombre,size_tpas);
//Accesseurs:
size_tstart()const;
size_tsize()const;
size_tstride()const;
};

Exemple1424.Slectionparindexationimplicite
#include <iostream>
#include <valarray>
usingnamespacestd;
voidaffiche(constvalarray
<int> &v)
{
size_ti;
for(i=0;i <v.size();++i)
cout << v[i] << "";
cout << endl;
}
intmain(void)
{
//Construitunvalarraydentier:
intvaleurs[]={1,5,9,4,3,7,21,32};
valarray<int> vi(valeurs,8);
affiche(vi);
//Multipliepar2unlmentsur3partirdudeuxime:
slicesel(1,3,3);
vi[sel]*=valarray<int>(2,vi.size());
affiche(vi);
//Multipliepar2unlmentsur3partirdudeuxime:
slicesel(1,3,3);

270

Chapitre14.Lestypescomplmentaires
vi[sel]*=valarray<int>(2,vi.size());
affiche(vi);
return0;
}

Laclassegsliceestenrevancheunpeuplusdifficiledemploipuisquilfautdonnerlenombrede
valeursetlepaspourchaquevariabledecontrle.Leconstructeurutilisprenddoncendeuximeet
troisimeparamtresnonplusdeuxvaleursdetypesize_t,maisdeuxvalarraydesize_t.Ladclaration
delaclassegsliceestdonclasuivante:
classgslice
{
public:
gslice();
gslice(size_tdebut,
constvalarray<size_t> nombres,
constvalarray<size_t> pas);
//Accesseurs:
size_tstart()const;
valarray<size_t> size()const;
valarray<size_t> stride()const;
};

Lesdeuxvalarraydterminantlenombredevaleursdesvariablesdecontrleetleurspasdoiventbien
entenduavoirlammetaille.Lordredanslequellesindicesdeslmentsslectionnssontgnrs
parlaclassegsliceestceluiobtenuenfaisantvarierenpremierlesderniresvariablescaractrises
parlesvalarrayfournislorsdesaconstruction.Parexemple,uneclassegsliceutilisanttroisvariables
prenantrespectivement2,3et5valeursetvariantrespectivementparpasde3,1et2units,enpartant
delindice2,gnreralesindicessuivants:
2,4,6,8,10,
3,5,7,9,11,
4,6,8,10,12,
5,7,9,11,13,
6,8,10,12,14,
7,9,11,13,15

Lavariableprenantcinqvaleursetvariantdedeuxendeuxestdonccellequivolueleplusvite.
Commevouspouvezleconstateraveclexempleprcdent,unmmeindicepeutapparatreplusieurs
foisdanslasriedfinieparuneclassegslice.LabibliothquestandardC++neffectueaucuncontrle
ceniveau:ilestdoncduressortduprogrammeurdebienfaireattentioncequilfaitlorsquil
manipuledesjeuxdindicesdgnrs.
Commepourlesautrestechniquesdeslection,laslectiondlmentsdunvalarraynonconstantpar
lintermdiairedesclassessliceetgsliceretourneuneinstanceduneclasseparticulirepermettantde
prendreenchargelesoprationsdemodificationdeslmentsainsislectionns.Pourlesslections
simplesralisesaveclaclasseslice, lobjet retournest detypeslice_array. Pourlesslections
ralisesaveclaclassegslice,letypeutilisestletypegslice_array.

271

Chapitre14.Lestypescomplmentaires
14.3.2.2.4. Oprations ralisables sur les slections multiples
Commeonlavudanslessectionsprcdentes,lesslectionsmultiplesralisessurdesobjetsnon
constantsretournent desinstancesdesclassesutilitairesmask_array, indexed_array, slice_arrayet
gslice_array.Cesclassesrfrencentleslmentsainsislectionnsdanslevalarraysource,permet
tantainsidelesmanipulerengroupe.Cependant,cenesontpasdesvalarraycompletset,enfait,ils
nedoiventtreutiliss, demaniregnrale, quepoureffectueruneoprationdaffectationsurles
lmentsslectionns.Cesclassesutilisentdoncuneinterfacerestreintedecelledelaclassevalarray,
quinacceptequelesoprateursdaffectationsurleslmentsquellesreprsentent.
Parexemple,laclassemask_arrayestdclarecommesuitdanslentte valarray :
template <classT >
classmask_array
{
public:
typedefTvalue_type;
~mask_array();
//Oprateursdaffectationetdaffectationcomposes:
voidoperator=(constvalarray<T> &)const;
voidoperator*=(constvalarray<T> &)const;
voidoperator/=(constvalarray<T> &)const;
voidoperator%=(constvalarray<T> &)const;
voidoperator+=(constvalarray<T> &)const;
voidoperator=(constvalarray<T> &)const;
voidoperator^=(constvalarray<T> &)const;
voidoperator&=(constvalarray<T> &)const;
voidoperator|=(constvalarray<T> &)const;
voidoperator<<=(constvalarray<T> &)const;
voidoperator>>=(constvalarray<T> &)const;
voidoperator=(constT&valeur);
};

Touscesoprateurspermettentdaffecterauxlmentsdelaslectionreprsentsparcetteclasse
lesvaleursspcifiesparleurparamtre.Engnral,cesvaleursdoiventtrefourniessouslaforme
dunvalarray,maisilexistegalementunesurchargedeloprateurdaffectationpermettantdeleur
affectertousunemmevaleur.
Note:Lesslectionsralisessurlesvalarrayconstantsnepermettent bienentendupasde
modifierleurslments. Lesobjetsretournsparloprateur [] lorsdesslectionsmultiples
surcesobjetssontdoncdesvalarrayclassiquescontenantunecopiedesvaleursdeslments
slectionns.

14.3.3.Leschampsdebits
Detouslestypesdedonnesquunprogrammepeutavoirbesoindestocker,lesboolenssontcertai
nementlundesplusimportants.Eneffet,lesprogrammesdoiventsouventreprsenterdesproprits
qui sont soit vraies, soit fausses. Aprstout, labasedutraitement delinformationtellequil est
ralisparlesordinateursestlebit,ouchiffrebinaire...

272

Chapitre14.Lestypescomplmentaires
Ilexisteplusieursmaniresdestockerdesboolensdansunprogramme.Latechniquelaplussimple
estbienentendudutiliserletypeC++natifbool,quinepeutprendrequelesvaleurstrue et false.
Lesprogrammesplusvieuxutilisaientgnralementdesentiersetdesconstantesprdfiniesouen
coreunenumration. Malheureusement, toutescestechniquessouffrentdugrosinconvnientque
chaqueinformationeststockedansletypesousjacentautypeutilispourreprsenterlesboolens
et,danslaplupartdescas,cetypeestunentier.Celasignifiequepourstockerunbit,ilfautrserverun
motmmoirecomplet.MmeentenantcomptedufaitquelaplupartdescompilateursC++stockent
lesvariablesdetypebooldansdesimplesoctets,ladperditionrestedansunfacteur8.Bienentendu,
celanestpasgravesilonnaquequelquesbitsstocker,maissileprogrammedoitmanipulerun
grandnombredinformationsboolennes,cettetechniqueestproscrire.
NousavonsvudanslaSection3.1.4quilestpossiblededfinirdeschampsdebitsenattribuant
unnombredebitsfixeplusieursidentificateursdetypeentier.
Cettesolutionpeut permettre
dconomiserdelammoire,maisrestemalgrtoutrelativementlimitesiungrandnombredebits
doit tremanipul. Afindersoudreceproblme, labibliothquestandardC++fournit laclasse
template bitsetqui,commesonnomlindique,encapsuledeschampsdebitsdetaillesarbitraires.
Leparamtre template est detypesize_t et indiquelenombredebitsquelechampdebits
encapsulcontient.
Note:Vousnoterezquecelaimposedeconnatrelacompilationlatailleduchampdebits.
Celaestregrettableetlimitesrieusementlintrtdecetteclasse.Sivousdevezmanipulerdes
champsdebitsdetailledynamique,vousdevrezcrirevousmmeuneclassedencapsulation
dynamiquedeschampsdebits.

Laclassebitsetestdclarecommesuitdanslentte bitset :
template <size_tN >
classbitset
{
public:
classreference;

//Classepermettantdemanipulerlesbits.

//Lesconstructeurs:
bitset();
bitset(unsignedlongval);
template<classcharT,classtraits,classAllocator
>
explicitbitset(
constbasic_string<charT,traits,Allocator> &chaine,
typenamebasic_string<charT,traits,Allocator
>::size_typedebut=0,
typenamebasic_string<charT,traits,Allocator
>::size_typetaille=
basic_string<charT,traits,Allocator
>::npos);
//Lesfonctionsdeconversion:
unsignedlongto_ulong()const;
template <classcharT,classtraits,classAllocator
>
basic_string<charT,traits,Allocator> to_string()const;
//Lesoprateursdemanipulation:
bitset<N> &operator&=(constbitset<N> &);
bitset<N> &operator|=(constbitset<N> &);
bitset<N> &operator^=(constbitset<N> &);
bitset<N> &operator<<=(size_tpos);
bitset<N> &operator>>=(size_tpos);
bitset<N> operator<<(size_tpos)const;

273

Chapitre14.Lestypescomplmentaires
bitset<N> operator>>(size_tpos)const;
bitset<N> operator~()const;
bitset<N> &set();
bitset<N> &set(size_tpos,boolval=true);
bitset<N> &reset();
bitset<N> &reset(size_tpos);
bitset<N> &flip();
bitset<N> &flip(size_tpos);
booltest(size_tpos)const;
referenceoperator[](size_tpos); //forb[i];
//Lesoprateursdecomparaison:
booloperator==(constbitset<N> &rhs)const;
booloperator!=(constbitset<N> &rhs)const;
//Lesfonctionsdetest:
size_tcount()const;
size_tsize()const;
boolany()const;
boolnone()const;
};

Laconstructiondunchampdebitsncessitedeconnatrelenombredebitsquecechampdoitconte
nirafindinstancierlaclasse template bitset.Lesdiffrentsconstructeurspermettentdinitialiserle
champdebitsenaffectantlavaleurnulletoussesbitsouenlesinitialisantenfonctiondespara
mtresduconstructeur. Ledeuximeconstructeuraffecteraauxpremiersbitsduchampdebitsles
bitscorrespondantdelentierdetypeunsignedlongfournienparamtre,etinitialiseralesautresbits
duchampdebitslavaleur0siceluicicontientplusdebitsquununsignedlong.
Letroisime
constructeurinitialiselechampdebitspartirdesareprsentationsousformedechanedecarac
tresnecontenantquedes 0oudes 1.Cettereprsentationdoittrestockedanslabasic_string
fournieenpremierparamtre,partirdelapositiondebut etsurunelongueurde taille caractres.
Cettetaillepeuttreinfrieurelatailleduchampdebits.Danscecas,leconstructeurconsidrera
quelesbitsdepoidsfortsonttousnulsetinitialiseralespremiersbitsduchampaveclesvaleurslues
danslachane.Notezbienquelespremierscaractresdelachanedecaractresreprsententlesbits
depoidsfort,cettechaneestdoncparcourueensensinverselorsdelinitialisation.Ceconstructeur
estsusceptibledelanceruneexception out_of_range sileparamtre debut estsuprieurlataille
delachaneouuneexception invalid_argument silundescaractresutilissestdiffrentdes
caractres 0ou 1.
Commevouspouvezleconstaterdaprsladclaration,
laclassebitsetfournitgalementdesm
thodespermettantdeffectuerlesconversionsinversesdecelleseffectuesparlesconstructeurs.La
mthode to_ulong renvoiedoncunentierdetypeunsignedlongcorrespondantlavaleurdespre
templateto_stringrenvoieunechanedecaractres
miersbitsduchampdebits,etlamthode
contenantlareprsentationduchampdebitssouslaformedunesuitedecaractres 0et 1. La
classebitsetfournitgalementdessurchargesdesoprateurs operator<< et operator>> pourles
fluxdentre/sortiedelabibliothquestandard.
Exemple1425.Utilisationdunbitset
#include <iostream>
#include <bitset>
#include <string>
usingnamespacestd;

274

Chapitre14.Lestypescomplmentaires

intmain(void)
{
//Construitunchampdebits:
strings("100110101");
bitset<32> bs(s);
//Affichelavaleurenhexadcimaldelentierassoci:
cout << hex << showbase << bs.to_ulong() << endl;
//Affichelavaleursousformedechanedecaractres:
stringt;
t=bs.to_string<string::value_type,string::traits_type,
string::allocator_type
>();
cout << t << endl;
//Utilisedirectement << surlefluxdesortie:
cout << bs << endl;
return0;
}
Note:Lamthode to_string estunefonction template neprenantpasdeparamtres.Lecom
pilateurnepeutdoncpasraliseruneinstanciationimplicitelorsdesonappel.Parconsquent,
vousdevrezfournirlalistedesparamtres template explicitementsi vousdsirezutilisercette
mthode.Ilestgnralementplussimpledcrirelavaleurdubitsetdansunfluxstandard.
Lesmodificateursdeformat deflux hex et showbase ont pour but deffectuer laffichagedes
entierssousformehexadcimale.Lapersonnalisationdesfluxdentre/sortieseradcriteen
dtaildansleChapitre15.

Lesoprateursdemanipulationdeschampsdebitsneposentpasdeproblmeparticulierpuisquils
ontlammesmantiquequelesoprateursstandardsdulangage,
ceciprsquilstravaillentsur
lensembledesbitsduchampenmmetemps.Leseuloprateurquidemandequelquesexplications
estloprateurdaccsunitaireauxbitsduchamp, savoirloprateur operator[]. Eneffet, cet
oprateurnepeutpasretournerunerfrencesurlebitdsignparsonargumentpuisquilnyapas
detypepourreprsenterlesbitsenC++.Parconsquent,lavaleurretourneestenralituneinstance
delasousclassereferencedelaclassebitset.Cettesousclasseencapsulelaccsindividuelauxbits
dunchampdebitset permet delesutiliserexactement commeunboolen. Enparticulier, il est
possibledefairedestestsdirectementsurcettevaleurainsiquedeluiaffectuerunevaleurboolenne.
Enfin,lasousclassereferencedisposedunemthode flip dontlerleestdinverserlavaleurdubit
auquellobjetreferencedonneaccs.
Laclasse template bitsetdisposegalementdemthodesspcifiquespermettantdemanipulerles
bitssansavoirrecoursloprateur operator[].Ilsagitdesmthodes test, set, reset et flip.
Lapremiremthodepermetdercuprerlavaleurcourantedundesbitsduchampdebits.
Elle
true silebitest 1 et false
prendenparamtrelenumrodecebitetrenvoieunboolenvalant
sinon.Lamthode set permetderinitialiserlechampdebitscompletenpositionnanttoussesbits
1oudefixermanuellementlavaleurdunbitparticulier.Latroisimemthodepermetderinitialiser
lechampdebitsenannulanttoussesbitsoudannulerunbitspcifique.
Enfin, lamthode flip
permet dinverserlavaleurdetouslesbitsduchampoudinverserlavaleurdunbit
spcifique.
Lessurchargesdesmthodesquitravaillentsurunseulbitprennenttoutesenpremierparamtrela
positiondubitdanslechampdebits.
Exemple1426.Manipulationdesbitsdunchampdebits
#include <iostream>
#include <string>

275

Chapitre14.Lestypescomplmentaires
#include <bitset>
usingnamespacestd;
intmain(void)
{
//Construitunchampdebits:
strings("10011010");
bitset<8> bs(s);
cout << bs << endl;
//Inverselechampdebits:
bs.flip();
cout << bs << endl;
//Fixelebitdepoidsfort:
bs.set(7,true);
cout << bs << endl;
//Annulele7mebitlaidedunerfrencedebit:
bs[6]=false;
cout << bs << endl;
//Anulelebitdepoidsfaibe:
bs.reset(0);
cout << bs << endl;
return0;
}

Enfin,laclassebitsetfournitquelquesmthodespermettantdeffectuerdestestssurleschampsde
count, size, any et
bits.Outrelesoprateursdecomparaisonclassiques,ellefournitlesmthodes
none.Lamthode count renvoielenombredebitspositionns1danslechampdebits.Lamthode
size renvoiequantellelatailleduchampdebits,cestdirelavaleurduparamtre
template
utilisepourinstancierlaclassebitset.Enfin,lesmthodes any et none renvoient true siunbitau
moinsduchampdebitsestpositionnousilssonttousnuls.

276

Chapitre15.Lesfluxdentre/sortie
NousavonsvudanslaSection8.12unexempledapplicationdesclassesdefluxdentre/sortiede
labibliothquepourlesentres/sortiesstandardsdesprogrammes.Enralit,cesclassesdegestion
desfluxsintgrentdansunehirarchiecomplexedeclassespermettantdemanipulerlesfluxdentre
/sortieetpasseulementpourlesentres/sortiesstandards.
Eneffet, afindefaciliterlamanipulationdesfluxdentre/
sortie, labibliothquestandardC++
template
fournittoutunensembledeclasses
.Cesclassessontparamtresparletypedebasedes
caractresquellesmanipulent. Bienentendu, lestypesdecaractreslesplusutilisssontlestype
charetwchar_t,maisilestpossibledutiliserapriorinimportequelautretypededonnepourlequel
uneclassedetraitschar_traitsestdfinie.
Cechapitreapourbutdedtaillercettehirarchiedeclasses.Lesprincipesdebaseetlarchitecture
gnraledesfluxC++serontdoncabordsdansunpremiertemps, puislesclassesdegestiondes
tamponsseronttraites. Lesclassesgnriquesdegestiondesfluxdentre/sortieserontensuite
dcrites,etceseraenfinletourdesclassesdegestiondesfluxorientschanesdecaractresetdes
classesdegestiondesfluxorientsfichiers.

15.1.Notionsdebaseetprsentationgnrale
Lesclassesdelabibliothquedentre/sortiedelabibliothquestandardsesubdivisentendeux
catgoriesdistinctes.
Lapremirecatgorieregroupelesclassesdegestiondestamponsdentre/sortie.Cesclassessont
aunombredetrois:laclasse template basic_stringbuf,quipermetderaliserdestamponspourles
fluxorientschanesdecaractres,laclasse template basic_filebuf,quiprendenchargelestampons
pourlesfluxorientsfichiers,etleurclassedebasecommune,laclasse template basic_streambuf.
Lerledecesclassesestprincipalementdoptimiserlesentres/sortiesenintercalantdestampons
dentre/sortieauseinmmeduprogramme.Cesontprincipalementdesclassesutilitaires,quisont
utiliseseninterneparlesautresclassesdelabibliothquedentre/sortie.
Ladeuximecatgoriedeclassesestdeloinlapluscomplexe,puisquilsagitdesclassesdegestion
desfluxeuxmmes.Toutescesclassesdriventdelaclassetemplate basic_ios(ellemmedrive
delaclassedebaseios_base, quidfinittouslestypesetlesconstantesutilissparlesclassesde
flux).Laclassebasic_iosfournitlesfonctionnalitsdebasedesclassesdefluxet,enparticulier,elle
grelelienaveclestamponsdentre/sortieutilissparleflux.Decetteclassedebasedriventdes
classesspcialisesrespectivementpourlesentresoupourlessorties.
Ainsi, laclasse template
basic_istreamprendenchargetouteslesoprationsdesfluxdentreet
laclassebasic_ostream
touteslesoprationsdesfluxdesortie. Enfin, labibliothquestandarddfinitlaclasse template
basic_iostream,quiregroupetouteslesfonctionnalitsdesclassesbasic_istreametbasic_ostreamet
dontdriventtouteslesclassesdegestiondesfluxmixtes.
Lesclassesbasic_istream, basic_ostreamet basic_iostreamfournissent lesfonctionnalitsdebase
desfluxdentre/sortie.Cesontdonclesclassesutilisespourimplmenterlesfluxdentre/sortie
standardsduC++ cin, cout, cerr et clog,quelonabrivementprsentsdanslaSection8.12.
Cependant,cesclassesneprennentpasenchargetouteslesspcificitsdesmdiasaveclesquelsdes
fluxpluscomplexespeuventcommuniquer. Parconsquent, desclassesdrives, plusspcialises,
sontfourniesparlabibliothquestandard. Cesclassesprennentenchargelesentres/sortiessur
fichieretlesfluxorientschanesdecaractres.
Labibliothquestandardfournit doncdeuxjeuxdeclassesspcialisespourlesentres/
sorties
dansdesfichiersetdansdeschanesdecaractres.Pourchacunedesclassesdebasebasic_istream,

277

Chapitre15.Lesfluxdentre/sortie
basic_ostreamet basic_iostreamil existedeuxclassesdrives, unepourlesfichiers, et unepour
leschanesdecaractres.Parexemple,lesclasses template basic_ifstreametbasic_istringstream
driventdelaclassebasic_istreametprennentenchargerespectivementlesfluxdentrepartirde
fichiersetlesfluxdentrepartirdechanesdecaractres.Demme,labibliothquestandarddfinit
lesclasses template basic_ofstreamet basic_ostringstream, drivesdelaclassebasic_ostream,
template
pourlesfluxdesortiedansdesfichiersoudansdeschanesdecaractres,etlesclasses
basic_fstreamet basic_stringstream, drivesdelaclassebasic_iostream, pourlesfluxdentre/
sortiesurlesfichiersetleschanesdecaractres.
Note: Cettehirarchiedeclassesest assezcomplexeet peut paratretrangeauniveau
desclassesdesfluxmixtes. Eneffet, laclassebasic_fstreamnedrivepasdesclasses
basic_ifstreamet basic_ofstreammaisdelaclassebasic_iostream, et cest cetteclassequi
drivedesclassesbasic_istreamet basic_ostream. Demme, laclassebasic_stringstream
nedrivepasdesclassesbasic_istringstreamet
basic_ostringstream, maisdelaclasse
basic_iostream.

Commeilladjtdit,toutescesclasses template peuventtreinstanciespournimportequel


typedecaractre, pourvuquuneclassedetraitschar_traitssoitdfinie. Cependant, enpratique, il
nestcourantdinstanciercesclassesquepourlestypesdecaractresdebasedulangage,savoirles
typescharetwchar_t.
Historiquement,lesclassesdentre/sortiedesbibliothquesfourniesaveclaplupartdesimplmen
tationsntaientpas template etnepermettaientdemanipulerquedesfluxbasssurletypede
caractrechar. Lesimplmentationsdisposantdeclassesdefluxdentre/sortiecapablesdema
nipulerlescaractresdetypewchar_ttaientdoncrelativementrares.prsent,toutescesclasses
sontdfiniescommedesinstancesdesclasses template citescidessus.Parsoucidecompatibilit,
labibliothquestandardC++dfinittoutunjeudetypespourcesinstancesquipermettentauxpro
grammesutilisantlesanciennesclassesdefonctionner.Cestypessontdclarsdelamaniresuivante
danslentte iosfwd (maissontdfinisdansleursenttesrespectifs,quelondcriraplustard):
//Typesdebasedestampons:
typedefbasic_streambuf<char>
typedefbasic_streambuf<wchar_t>
typedefbasic_stringbuf<char>
typedefbasic_stringbuf<wchar_t>
typedefbasic_filebuf<char>
typedefbasic_filebuf<wchar_t>

streambuf;
wstreambuf;
stringbuf;
wstringbuf;
filebuf;
wfilebuf;

//Typesdebasedesfluxdentre/sortie:
typedefbasic_ios<char>
ios;
typedefbasic_ios<wchar_t> wios;
//Typesdesfluxdentre/sortiestandards:
typedefbasic_istream<char>
istream;
typedefbasic_istream<wchar_t> wistream;
typedefbasic_ostream<char>
ostream;
typedefbasic_ostream<wchar_t> wostream;
typedefbasic_iostream<char>
iostream;
typedefbasic_iostream<wchar_t> wiostream;
//Typesdesfluxorientsfichiers:
typedefbasic_ifstream<char>
ifstream;
typedefbasic_ifstream<wchar_t> wifstream;
typedefbasic_ofstream<char>
ofstream;

278

Chapitre15.Lesfluxdentre/sortie
typedefbasic_ofstream<wchar_t> wofstream;
typedefbasic_fstream<char>
fstream;
typedefbasic_fstream<wchar_t> wfstream;
//Typesdesfluxorientschanesdecaractres:
typedefbasic_istringstream
istringstream;
<char>
typedefbasic_istringstream
<wchar_t> wistringstream;
typedefbasic_ostringstream
ostringstream;
<char>
typedefbasic_ostringstream
<wchar_t> wostringstream;
typedefbasic_stringstream
stringstream;
<char>
typedefbasic_stringstream
<wchar_t> wstringstream;

Lesobjets cin, cout, cerr et clog sontdoncdesinstancesdesclassesistreametostream,quisont


associesauxfluxdentre/sortiestandardsduprogramme.Enfait,labibliothquestandarddfinit
galementdesversionscapablesdemanipulerdesfluxbasssurletypewchar_tpourlesprogrammes
quidsirenttravailleravecdescaractreslarges. Cesobjetssontrespectivement wcin (instancede
wistream), wcout, wcerr et wclog (instancesdewostream).Touscesobjetssontinitialissparla
bibliothquestandardautomatiquement lorsquilssont utilisspourlapremirefois, et sont donc
toujoursutilisables.
Note:Enralit,surlaplupartdessystmes,lesfluxdentre/sortiestandardssontlespremiers
descripteursdefichiersquelesystmeattribueautomatiquementauxprogrammeslorsquilssont
lancs.Entoutelogique,lesobjetscin, cout, cerr et clog devraientdonctredesinstancesde
classesdegestiondefluxorientsfichiers.Cependant,cesfichiersnesontpasnommsdune
part et, dautrepart, touslessystmesnegrent paslesfluxdentre/ sortiestandardsdela
mmemanire.Cesobjetsnesontdoncpastoujoursdesfluxsurdesfichiersetlabibliothque
standardC++nelesdfinitparconsquentpascommetels.

15.2.Lestampons
LesclassesdegestiondestamponsdelabibliothquestandardC++sesituentaucoeurdesoprations
dcritureetdelecturesurlesfluxdedonnesphysiquesquunprogrammeestsusceptibledemani
puler.Bienquellesnesoientquasimentjamaisutilisesdirectementparlesprogrammeurs,cestsur
cesclassesquelesclassesdefluxsappuientpoureffectuerlesoprationsdentresortie.Ilestdonc
ncessairedeconnatreunpeuleurmodedefonctionnement.

15.2.1.Gnralitssurlestampons
Untampon,galementappelcache,estunezonemmoiredanslaquellelesoprationsdcritureet
delecturesefontetdontlecontenuestmisencorrespondanceaveclesdonnesdunmdiaphysique
sousjacent. Lesmcanismesdecacheont essentiellement pourbut doptimiserlesperformances
desoprationsdentre/ sortie. Eneffet, laccslammoirecacheest gnralement beaucoup
plusrapidequelaccsdirectausupportphysiqueouaumdiadecommunication. Lesoprations
effectuesparleprogrammesefontdonc,laplupartdutemps,uniquementauniveaudutampon,et
cenestquedanscertainesconditionsquelesdonnesdutamponsonteffectivementtransmisesau
mdiaphysique.Legainenperformancepeutintervenirplusieursniveau.Lescaslesplussimples
tantsimplementlorsquunedonnecriteestcrasepeudetempsaprsparuneautrevaleur(la
premireoprationdcriturenestalorsjamaistransmiseaumdia)oulorsquunedonneestlue

279

Chapitre15.Lesfluxdentre/sortie
plusieursfois(lammedonneestrenvoyechaquelecture).Bienentendu,celasupposequeles
donnesstockesdansletamponsoientcohrentesaveclesdonnesdumdia,surtoutsilesdonnes
sontaccdesautraversdeplusieurstampons.Toutmcanismedegestiondecachepermetdoncde
viderlescaches(cestdiredeforcerlesoprationsdcriture)etdelesinvalider(cestdirede
leursignalerqueleursdonnessontobsoltesetquunelecturephysiquedoittrefaitesioncherche
yaccder).
Lesmcanismesdemmoirecacheetdetamponsonttrssouventutilisseninformatique,tousles
niveaux.Ontrouvedesmmoirescachedanslesprocesseurs,lescontrleursdedisque,lesgraveurs
deCD,lespilotesdepriphriquesdessystmesdexploitationetbienentendudanslesprogrammes.
Chacundecescachescontribuelamliorationdesperformancesglobalesenretardantaumaximum
laralisationdesoprationslentesetenoptimisantlesoprationsdelectureetdcriture(souventen
leseffectuantengroupe,cequipermetderduirelesfraisdecommunicationoudinitialisationdes
priphriques).IlnestdoncabsolumentpassurprenantquelabibliothquestandardC++utiliseelle
aussilanotiondetampondanstoutessesclassesdentre/sortie...

15.2.2.Laclassebasic_streambuf
Lesmcanismesdebasedestamponsdelabibliothquestandardsontimplmentsdanslaclasse
template basic_streambuf.Cetteclassenestpasdestinetreutilisetellequellecarellenesait
pascommuniqueraveclessupportsphysiquesdesdonnes.Enfait,ellenepeuttreutilisequen
tantqueclassedebasedeclassesplusspcialises,quiellesfournissentlesfonctionnalitsdaccs
auxmdiasparlintermdiairedefonctionsvirtuelles.Laclassebasic_streambuf appelledoncces
mthodesendiversescirconstancesauseindestraitementseffectusparsonproprecodedegestion
dutampon,aussibienpoursignalerleschangementsdtatdeceluiciquepourdemanderlcriture
oulalecturedesdonnesdanslasquencesouscontrle.
Laclassebasic_streambuffournitdoncuneinterfacepubliquepermettantdaccderauxdonnesdu
tampondunctetdfinitlinterfacedecommunicationavecsesclassesfillesparlintermdiairede
sesmthodesvirtuellesdelautrecot.Bienentendu,cesmthodesvirtuellessonttoutesdclares
enzoneprotgeafindviterquelonpuisselesappelerdirectement,toutenpermettantauxclasses
drivesdelesredfiniretdyaccder.
Eninterne, laclassebasic_streambufencapsuledeuxtampons, unpourlescrituresetunpourles
lectures. Cependant, cestamponsaccdentlammemmoireetlammesquencededonnes
physiques. Cesdeuxtamponspeuvent treutilisssimultanment ounon, suivant lanaturedela
squencesouscontrleetsuivantlefluxquiutiliseletampon.Parexemple,lesfluxdesortienutilisent
queletamponencriture,etlesfluxdentrequeletamponenlecture.
Laclassebasic_streambufgresestamponsdentreet desortielaidedunezonedemmoire
internequicontientunsousensembledesdonnesdelasquencesouscontrle.Lesdeuxtampons
travaillentdemanireindpendantesurcettezonedemmoireetsontchacunreprsentslaide
detroispointeurs.Cespointeurscontiennentrespectivementladressedudbutdelazonemmoire
dutampon, sonadressedefinet ladressedelapositioncouranteenlectureouencriture.
Ces
pointeurssontcompltementgrseninterneparlaclassebasic_streambuf,maislesclassesdrives
peuventyaccderetlesmodifierenfonctiondeleursbesoinsparlintermdiairedaccesseurs.Les
pointeursduntamponpeuvent parfaitement trenulssi celuici nest pasutilis. Toutefois, si le
pointeurrfrenantlapositioncourantenestpasnul,sespointeursassocisnedoiventpasltreet
lapositioncouranterfrencedoitobligatoirementsesituerdansunezonemmoiredfinieparles
pointeursdedbutetdefindutampon.
Laclassebasic_streambufestdclarecommesuitdanslentte streambuf :
template <classcharT,classtraits=

280

Chapitre15.Lesfluxdentre/sortie
char_traits<charT>>
classbasic_streambuf
{
public:
//Lestypesdebase:
typedefcharT
char_type;
typedeftypenametraits::int_typeint_type;
typedeftypenametraits::pos_typepos_type;
typedeftypenametraits::off_typeoff_type;
typedeftraits
traits_type;
//Lesmthodespubliquesutilisablesparlesclassesdeflux:
//Lesmthodesdegestiondeslocales:
localepubimbue(constlocale&loc);
localegetloc()const;
//Lesmthodesdegestiondutampon:
basic_streambuf<char_type,traits> *
pubsetbuf(char_type*s,streamsizen);
pos_typepubseekoff(off_typeoff,ios_base::seekdirsens,
ios_base::openmodemode=ios_base::in|ios_base::out);
pos_typepubseekpos(pos_typesp,
ios_base::openmodemode=ios_base::in|ios_base::out);
intpubsync();
//Mthodesdaccsautamponenlecture:
streamsizein_avail();
int_typesgetc();
int_typesbumpc();
int_typesnextc();
streamsizesgetn(char_type*s,streamsizen);
//Mthodedannulationdelectureduncaractre:
int_typesputbackc(char_typec);
int_typesungetc();
//Mthodedaccsencriture:
int_type
sputc(char_typec);
streamsizesputn(constchar_type*s,streamsizen);
//Ledestructeur:
virtual~basic_streambuf();
protected:
//Lesmthodesprotectedutilisablespar
//lesclassesdrives:
//Leconstructeur:
basic_streambuf();
//Mthodesdaccsauxpointeursdutampondelecture:
char_type*eback()const;
char_type*gptr() const;
char_type*egptr()const;
void
gbump(intn);
void
setg(char_type*debut,char_type*suivant,

281

Chapitre15.Lesfluxdentre/sortie
char_type*fin);
//Mthodesdaccsauxpointeursdutampondcriture:
char_type*pbase()const;
char_type*pptr()const;
char_type*epptr()const;
void
pbump(intn);
void
setp(char_type*debut,char_type*fin);
//Lesmthodesprotectedvirtuelles,quelesclasses
//drivesdoiventimplmenter:
virtualvoidimbue(constlocale&loc);
virtualbasic_streambuf<char_type,traits>*
setbuf(char_type*s,streamsizen);
virtualpos_typeseekoff(off_typeoff,ios_base::seekdirsens,
ios_base::openmodemode=ios_base::in|ios_base::out);
virtualpos_typeseekpos(pos_typesp,
ios_base::openmodemode=ios_base::in|ios_base::out);
virtualint
sync();
virtualint
showmanyc();
virtualstreamsizexsgetn(char_type*s,streamsizen);
virtualint_type
underflow();
virtualint_type
uflow();
virtualint_type
pbackfail(int_typec=traits::eof());
virtualstreamsizexsputn(constchar_type*s,streamsizen);
virtualint_type
overflow(int_typec=traits::eof());
};

Commevouspouvezleconstater, leconstructeurdelaclassebasic_streambufestdclarenzone
protected,cequiempchequiconquedelinstancier.Cestnormal,puisquecetteclassenestdesti
netreutilisequentantqueclassedebaseduneclassespcialisepourunmdiaspcifique.En
revanche,lesmthodesvirtuellesnesontpaspures,carellesfournissentuncomportementpardfaut
quiconviendradanslaplupartdescas.
Linterfacepubliquecomprenddesmthodesdordregnraleetdesmthodespermettantdeffectuer
lesoprationsdcritureetdelecturesurlestamponsencapsulsparlaclassebasic_streambuf.Pour
lesdistinguerdesmthodesvirtuellesquidoiventtreimplmentesdanslesclassesdrives,leur
nomestprfixpar pub (pourpublique).
Lesmthodes pubimbue et locale permettentrespectivementdefixerlalocaleutiliseparlepro
grammepourcetamponetdercuprerlalocalecourante. Pardfaut, lalocaleglobaleactiveau
momentdelaconstructiondutamponestutilise.LesnotionsdelocalesserontdcritesdansleCha
pitre16.
Lesmthodes pubsetbuf, pubseekoff et pubseekpos permettent quant ellesdeparamtrer
letampondentre/sortie. Cesmthodessecontententdappelerlesmthodesvirtuelles setbuf,
seekoff et seekpos, dont lecomportement, spcifiquechaqueclassedrive, seradcrit ci
dessous.
Viennentensuitelesmthodesdaccsauxdonnesenlectureetencriture.Lesmthodesdelecture
sontrespectivementlesmthodes sgetc, sbumpc et snextc.Lamthode sgetc permetdelirela
valeurducaractrerfrencparlepointeurcourantdutampondentre.
Cettefonctionrenvoiela
mmevaleurchaqueappel,carellenemodifiepaslavaleurdecepointeur.Enrevanche,lamthode
sbumpc faitavancercepointeuraprslalectureducaractrecourant,
cequifaitquellepeuttre
utilisepourliretouslescaractresdufluxdedonnesphysiques.Enfin,lamthode snextc appelle

282

Chapitre15.Lesfluxdentre/sortie
lamthode sbumpc dansunpremiertemps,puisrenvoielavaleurretourneparsgetc.Cettemthode
permetdoncdelirelavaleurducaractresuivantdansletamponetdepositionnerlepointeursurce
caractre.Notezque,contrairementlamthode sbumpc, snextc modifielavaleurdupointeuravant
delirelecaractrecourant,cequifaitquenralitellelitlecaractresuivant.Toutescesmthodes
renvoientlavaleurdefindefichierdfiniedanslaclassedestraitsdutypedecaractreutilisencas
derreur.Ellessontgalementsusceptiblesdedemanderlalecturededonnescomplmentairesdans
lecadredelagestiondutampon.
Lamthode in_avail renvoielenombredecaractresencorestocksdansletampongrparla
classebasic_streambuf.Sicetamponestvide,ellerenvoieuneestimationdunombredecaractres
quipeuventtrelusdanslasquencecontrleparletampon.Cetteestimationestunminimum,la
valeurrenvoyegarantitquautantdappel sbumpc russiront.
Lestamponsdelabibliothquestandarddonnent lapossibilitauxprogrammesqui lesutilisent
dannulerlalectureduncaractre.Normalement,cegenredannulationnepeuttreeffectuquune
seulefoisetlavaleurquidoittrereplacedansletampondoittreexactementcellequiavaitt
lue. Lesmthodesquipermettentdeffectuercetypedoprationsontlesmthodes sputbackc et
sungetc.Lapremiremthodeprendenparamtrelavaleurducaractrequidoittrereplacdans
letamponetladeuximenefaitquedcrmenterlepointeurrfrenantllmentcourantdansle
tampondelecture.Cesdeuxoprationspeuventchouersilavaleurreplacernestpasgalela
valeurducaractrequisetrouvedansletamponousi,toutsimplement,ilestimpossiblederevenir
enarrire(parexempleparcequonsetrouveendbutdesquence).Danscecas,cesmthodesren
voientlavaleurdefindefichierdfiniedanslaclassedestraitsdutypedecaractreutilis,savoir
traits::eof().
Enfin,lesmthodesdcrituredelaclassebasic_streambufsontlesmthodes sputc et sputn.La
premirepermetdcrireuncaractreuniquedansletampondelasquencedesortieetladeuxime
dcriretouteunesriedecaractres.Danscederniercas,lescaractrescriresontspcifislaide
duntableaudontlalongueurestpasseendeuximeparamtresputn.Cesdeuxmthodespeuvent
renvoyerlecaractredefindefichierdelaclassedestraitsdutypedecaractreutilispoursignaler
uneerreurdcriture.
Linterfaceprotgedelaclassebasic_streambufestconstituedesaccesseursauxpointeurssurles
tamponsdentreetdesortiedunepartet,dautrepart,desmthodesvirtuellesquelesclassesdri
vesdoiventredfinirpourimplmenterlagestiondesentres/sortiesphysiques.
Lespointeursdutableaucontenantlesdonnesdutampondelecturepeuventtrercuprsparles
classesdriveslaidedesmthodes eback, gptr et egptr.Lamthode eback renvoielepointeur
surledbutdutableaudutampondentre.Lesmthodes gptr et egptr renvoientquantellesle
pointeursurllmentcourant,dontlavaleurpeuttreobtenueaveclamthodesgetc,etlepointeur
surlafindutableaudutampon.Lenomdelamthode gptr provientdelabrviationdelanglais
getpointeretceluidelamthode egptr delabrviationendofgptr. Enfin, lesmthodes
gbump et setg permettent respectivement defaireavancerlepointeursurllment courant dun
certainnombredepositionsetdefixerlestroispointeursdutampondelectureenuneseuleopration.
Lespointeursdutampondcrituresont accessiblespardesmthodessimilairescellesdfinies
pourletampondelecture. Ainsi, lesmthodes pbase, pptr et epptr permettentrespectivement
daccderaudbut dutableaucontenant lesdonnesdutampondcriture, lapositioncourante
pourlescrituresetaupointeurdefindecetableau.pptresticilabrviationdelanglaisput
pointer.Lesmthodes pbump et setp jouentlemmerlepourlespointeursdutampondcriture
quelesmthodes gbump et setg pourlespointeursdutampondelecture.
Enfin, lesmthodesprotgesdelaclassebasic_streambufpermettent, commeonladjindiqu
cidessus,decommuniqueraveclesclassesdrivesimplmentantlesentres/sortiesphysiques.Le
rledecesmthodesestdcritdansletableaucidessous:

283

Chapitre15.Lesfluxdentre/sortie
Mthode

284

Description

imbue

Cettemthodeestappelechaquefoisquilyaunchangementdelocaleau
niveaudutampon.Lesclassesdrivesdelaclassebasic_streambufsont
assuresquilnyaurapasdechangementdelocaleentrechaqueappelcette
fonctionetpeuventdoncmaintenirunerfrencesurlalocalecouranteen
permanence.Lesnotionsconcernantleslocalesserontdcritesdansle
Chapitre16.

setbuf

Cettemthodenestappelequeparlamthode pubsetbuf.Ellea
principalementpourbutdefixerlazonemmoireutiliseparletampon.Ceci
peutnepasavoirdesenspourcertainsmdias,aussicettemthodepeutellene
rienfairedutout.Enpratique,sicettefonctionestappelleavecdeux
paramtresnuls,lesmcanismesdegestionducachedoiventtredsactivs.
Pourcela,laclassedrivedoitfixerlespointeursdestamponsdelectureet
dcriturelavaleurnulle.

seekoff

Cettemthodenestappelequeparlamthode pubseekoff.Toutcommela
mthode setbuf,sasmantiqueestspcifiquechaqueclassedrivede
gestiondesmdiasphysiques.Engnral,cettefonctionpermetdedplacerla
positioncourantedanslasquencededonnesduncertaindcalage.Ce
dcalagepeuttrespcifirelativementlapositioncourante,audbutoula
findelasquencededonnessouscontrle.Lemodededplacementest
spcifilaideduparamtre sens,quidoitprendrelunedesconstantesde
typeseekdirdfiniedanslaclasseios_base.Demme,letamponconcernpar
cedplacementestspcifiparleparamtre mode,dontlavaleurdoittre
lunedesconstantedetypeios_base::openmode.Cestypesetcesconstantes
serontdcritsaveclaclassedebaseios_basedanslaSection15.3.

seekpos

Cettemthodenestappelequeparlamthode pubseekpos.Ellefonctionne
demaniresimilairelamthode seekoff puisquellepermetdepositionner
lepointeurcourantdestamponsdelaclassebasic_streambufun
emplacementarbitrairedanslasquencededonnessouscontrle.

sync

Cettemthodenestappelequeparlamthode pubsync etpermetde


demanderlasynchronisationdutamponaveclasquencededonnes
physiques.Autrementdit,lesoprationsdcrituresdoiventtreeffectuessur
lechampafindesassurerquelesmodifiationseffectuesdanslecachesoient
bienenregistres.

showmanyc

Cettemthodeestappeleparlamthode in_avail lorsquelafindutampon


delectureatatteinte.Elledoitrenvoyeruneestimationbassedunombrede
caractresquipeuventencoretrelusdanslasquencesouscontrle.Cette
estimationdoittresre,danslesensolenombredecaractresrenvoysdoit
effectivementpouvoirtrelusanserreur.

xsgetn

Cettemthodenestappelequeparlamthode sgetn.Ellepermetdeffectuer
lalecturedeplusieurscaractresetdelesstockerdansletableaureuen
paramtre.Lalecturedechaquecaractredoitsefaireexactementcommesila
mthode sbumpc taitappelesuccessivementpourchacundeuxafinde
maintenirletampondelecturedansuntatcohrent.Lavaleurretourneestle
nombredecaractreseffectivementlusou traits::eof() encasderreur.

Chapitre15.Lesfluxdentre/sortie
Mthode
underflow

Description
Cettemthodeestappelelorsquelafindutamponestatteintelorsdela
lectureduncaractre.Celapeutseproduirelorsquilnyaplusdecaractre
disponibledansletamponoutoutsimplementchaquelecture,lorsquele
mcanismedecacheestdsactiv.Cettefonctiondoitrenvoyerlecaractre
suivantdelasquencesouscontrleetremplirletamponsincessaire.Le
pointeurrfrenantlecaractrecourantestalorsinitialissurlecaractredont
lavaleuratrcupre.Ainsi,lamthode underflow doitremplirle
tampon,maisnedoitpasfaireavancerlapositioncourantedelecture.Cette
mthodepeutrenvoyer traits::eof() encasdchec,cequiseproduit
gnralementlorsquelafindelasquencesouscontrleatatteinte.

uflow

Cettemthodeestappeledanslesmmesconditionsquelamthode
underflow.Elledoitgalementremplirletampon,mais,contrairement
underflow,ellefaitgalementavancerlepointeurducaractrecourantdune
position.Ceciimpliquequecettemthodenepeutpastreutiliseaveclesflux
nonbufferiss.Engnral,cettemthodenapastreredfinieparcequele
codedelamthode uflow delaclassebasic_streambufeffectuecesoprations
ensappuyantsurlamthode underflow.Cettemthodepeutrenvoyer
traits::eof() encasdchec.

pbackfail

Cettemthodeestappelelorsquelamthode sputbackc choue,soitparce


quelepointeurdelecturesetrouveaudbutdutampondelecture,soitparce
quelecaractrequidoittrereplacdanslasquencenestpaslecaractrequi
vientdentreextrait.Cettemthodedoitprendreenchargeledplacement
descaractresdutamponpourpermettrelereplacementducaractrefournien
paramtreetmettrejourlespointeursdegestiondutampondelectureen
consquence.Ellepeutrenvoyerlavaleur traits::eof() poursignalerun
chec.

xsputn

Cettemthodenestappelequeparlamthode sputn.Ellepermetderaliser
lcrituredeplusieurscaractresdanslasquencedesortie.Cescaractressont
spcifisdansletableaufournienparamtre.Cescrituressontralises
exactementcommesilamthode sputc taitappelesuccessivementpour
chaquecaractreafindemaintenirletampondcrituredansuntatcohrent.
Lavaleurretourneestlenombredecaractrescritsou traits::eof() en
casderreur.

overflow

Cettemthodeestappeleparlesmthodesdcrituredelaclasse
basic_streambuflorsqueletampondcritureestplein.Elleapourbutde
dgagerdelaplacedanscetamponenconsommantunepartiedescaractres
situsentrelepointeurdedbutdutamponetlepointeurdepositiondcriture
courante.Elleestdoncsusceptibledeffectuerlescrituresphysiquessurle
mdiadesortieaucoursdecetteopration.Silcriturerussit,lespointeurs
degestiondutampondcrituredoiventtremisjourenconsquence.Dans
lecascontraire,lafonctionpeutrenvoyerlavaleur traits::eof() pour
signalerlerreuroulanceruneexception.

15.2.3.Lesclassesdetamponsbasic_streambufet

285

Chapitre15.Lesfluxdentre/sortie

basic_filebuf
Vouslaurezcompris,lcritureduneclassedrivedelaclassebasic_streambufprenantencharge
unmdiapeuttrerelativementtechniqueetdifficile. Heureusement, cettesituationneseprsente
quasiment jamais, parcequelabibliothquestandardC++fournit desclassesdrivesprenant en
chargelesdeuxsituationslesplusimportantes:lestamponsdaccsunechanedecaractresetles
tamponsdaccsauxfichiers.Cesclassessontrespectivementlesclasses template basic_stringbuf
etbasic_filebuf.

15.2.3.1.Laclassebasic_stringbuf
Laclassebasic_stringbufpermetdeffectuerdesentres/sortiesenmmoiredelammemanire
quesi ellestaient effectuessurunpriphriquedentre/ sortienormal. Lebut decetteclasse
nestvidemmentpasdoptimiserlesperformanceslaideduncachepuisquelesoprationssefont
destinationdelammoire,maisduniformiseretdepermettrelesmmesoprationsdeformatage
dansdeschanesdecaractresquecellesquelonpeutraliseraveclesfluxdentre/sortienormaux.
Laclassebasic_streambufdrivebienentendudelaclassebasic_streambufpuisquelledfinitles
oprationsfondamentalesdcritureet delecturedansunechanedecaractres. Elleest dclare
commesuitdanslentte sstream :
template <classcharT,
classtraits=char_traits
<charT>,
classAllocator=allocator
<chatT>>
classbasic_stringbuf:publicbasic_streambuf <charT,traits>
{
public:
//Lestypes:
typedefcharT
char_type;
typedeftypenametraits::int_typeint_type;
typedeftypenametraits::pos_typepos_type;
typedeftypenametraits::off_typeoff_type;
typedeftraits
traits_type;
//Lesconstructeurs/destructeurs:
explicitbasic_stringbuf(
ios_base::openmodemode=ios_base::in|ios_base::out);
explicitbasic_stringbuf(
constbasic_string<charT,traits,Allocator> &str,
ios_base::openmodemode=ios_base::in|ios_base::out);
virtual~basic_stringbuf();
//Lesmthodesdegestiondelachanedecaractressouscontrle:
basic_string<charT,traits,Allocator
> str()const;
voidstr(constbasic_string
<charT,traits,Allocator> &s);
};

Commecettedclarationlemontre,laclassebasic_streambufdfinitelleaussiunjeudetypespermet
tantdobtenirfacilementlestypesdeobjetsmanipuls.Deplus,elledfinitgalementquelquesm
thodescomplmentairespermettantdeffectuerlesoprationsspcifiquesauxfluxorientschanede
caractres.Enparticulier,lesconstructeurspermettentdefournirunechanedecaractrespartirde
laquelleletamponserainitialis.Cettechanedecaractresestcopielorsdelaconstructiondutam
pon,cequifaitquellepeuttrerutiliseoumodifieaprslacrationdutampon.Cesconstructeurs
prennentgalementenparamtrelemodedefonctionnementdutampon.Cemodepeuttrelalecture

286

Chapitre15.Lesfluxdentre/sortie
(auquelcasleparamtre mode vaut ios_base::in),lcriture( mode vautalors ios_base::out)
oulesdeux( mode vautalorslacombinaisondecesdeuxconstantesparunoulogique).Lesconstantes
demodedouverturesontdfinisdanslaclasseios_base,quelondcriradanslaSection15.3.
Note:Vousremarquerezque,contrairementauconstructeurdelaclassebasic_streambuf,les
constructeursdelaclassebasic_stringbuf sontdclarsdanslazonededclarationpublique,
cequi autoriselacrationdetamponsdetypebasic_stringbuf.Leconstructeurdelaclassede
baseestappelparcesconstructeurs,qui ontledroitdelefairepuisquil sagitdunemthode
protected.

Ilestgalementpossibledaccderauxdonnesstockesdansletamponlaidedesaccesseurs str.
Lepremierrenvoieunebasic_stringcontenantlachanedutamponencrituresipossible(cestdire
siletamponatcrdanslemodecritureoulecture/criture),etlachanedutamponenlecture
sinon.Ledeuximeaccesseurpermetdedfinirlesdonnesdutamponaposteriori,unefoisceluici
cr.
Exemple151.Lectureetcrituredansuntampondechanedecaractres
#include <iostream>
#include <string>
#include <sstream>
usingnamespacestd;
intmain(void)
{
//Construitunechanedecaractre:
strings("123456789");
//Construituntamponbassurcettechane:
stringbufsb(s);
//Litquelquescaractresunitairement:
cout << (char)sb.sbumpc() << endl;
cout << (char)sb.sbumpc() << endl;
cout << (char)sb.sbumpc() << endl;
//Replacelederniercaractreludansletampon:
sb.sungetc();
//Littroiscaractresconscutivement:
chartab[4];
sb.sgetn(tab,3);
tab[3]=0;
cout << tab << endl;
//craselepremiercaractredelachane:
sb.sputc(a);
//Rcupreunecopiedelachaneutiliseparletampon:
cout << sb.str() << endl;
return0;
}
Note:Laclassebasic_stringbufredfinitbienentenducertainesdesmthodesprotgesdela
classebasic_streambuf.Cesmthodesnontpastprsentesdansladclarationcidessus
parcequellesfontpartiedelimplmentationdelaclassebasic_stringbufetleurdescriptionna
quepeudintrtpourlesutilisateurs.

287

Chapitre15.Lesfluxdentre/sortie

15.2.3.2.Laclassebasic_filebuf
Laclassebasic_filebufestlaclassequiprendenchargelesoprationsdentre/sortiesurfichierdans
labibliothquestandardC++.
PourlabibliothquestandardC++,unfichierestunesquencedecaractressimples(doncdetype
char). Ilestimportantdebiencomprendrequilnestpaspossible,
aveclaclassebasic_filebuf, de
manipulerdesfichierscontenant desdonnesdetypewchar_t. Eneffet, mmedanslecasoles
donnesenregistressontdetypewchar_t,lesfichierscontenantcesdonnessontenregistrssousla
formedesquencesdecaractresdontlunitdebaserestelecaractresimple.Lamaniredecoder
lescaractreslargesdanslesfichiersnestpasspcifieetchaqueimplmentationestlibredefaire
cequelleveutceniveau.Gnralement,lencodageutilisestunencodagetaillevariable,cest
direquechaquecaractrelargeestreprsentsouslaformedunoudeplusieurscaractressimples,
selonsavaleuretselonsapositiondanslefluxdedonnesdufichier.
Celasignifiequil nefaut pasfairedhypothsesur lamaniredont lesinstancesdelaclasse
template basic_filebuf enregistrent les donnes des fichiers pour des valeurs duparamtre
templatecharT autres queletypechar. Engnral, lencodageutilisneconcernepas
le
programmeur, puisquil suffit denregistreret delirelesfichiersaveclesmmetypesdeclasses
basic_filebufpourretrouverlesdonnesinitiales. Toutefois, si lesfichiersdoivent trereluspar
desprogrammescritsdansunautrelangageoucompilsavecunautrecompilateur,
il peut tre
ncessairedeconnatrelencodageutilis. Voustrouverezcetteinformationdansladocumentation
devotreenvironnementdedveloppement.
Laclassebasic_filebufestdclarecommesuitdanslentte fstream :
template <classcharT,
classtraits=char_traits
<charT>>
classbasic_filebuf:publicbasic_streambuf<charT,traits>
{
public:
//Lestypes:
typedefcharT
char_type;
typedeftypenametraits::int_typeint_type;
typedeftypenametraits::pos_typepos_type;
typedeftypenametraits::off_typeoff_type;
typedeftraits
traits_type;
//Lesconstructeurs/destructeurs:
basic_filebuf();
virtual~basic_filebuf();
//Lesmthodesdegestiondufichiersouscontrle:
basic_filebuf<charT,traits> *open(constchar*s,
ios_base::openmodemode);
basic_filebuf<charT,traits> *close();
boolis_open()const;
};

Commevouspouvezleconstater, laclassebasic_filebufestsemblablelaclassebasic_stringbuf.
Outrelesdclarationsdetypesetcellesduconstructeuretdudestructeur,elledfinittroismthodes
permettantderaliserlesoprationsspcifiquesauxfichiers.
Lamthode open permet,commesonnomlindique,douvrirunfichier.Cettemthodeprendenpa
ramtrelenomdufichierouvrirainsiquelemodedouverture.Cemodepeuttreunecombinaison
logiquedeplusieursconstantesdfiniesdanslaclasseios_base.Cesconstantessontdcritesdansla

288

Chapitre15.Lesfluxdentre/sortie
Section15.3.Lesplusimportantessontin,quipermetdouvrirunfichierenlecture,out,quipermet
delouvrirenlecture, binary,quipermetdelouvrirenmodebinaire, app,quipermetdelouvrir
enmodeajout,et trunc,quipermetdeleviderlorsquilestouvertencriture.Lamthode open
renvoielepointeur this silefichieraputreouvertoulepointeurnuldanslecascontraire.
Laclassebasic_filebufnegrequuneseulepositionpourlalectureetlcrituredanslesfichiers.
Autrementdit, siunfichierestouvertlafoisenlectureetencriture,
lespointeursdelectureet
dcrituredutamponauronttoujourslammevaleur.Lcritureunepositionprovoqueradoncnon
seulement lamodificationdelapositioncouranteencriture, maisgalement celledelaposition
couranteenlecture.
Lamthode close estlamthodeutiliserpourfermerunfichierouvert. Cettemthodenepeut
fonctionnerquesiunfichieresteffectivementouvertdanscetampon.Ellerenvoielepointeur this
silefichiercourantaeffectivementputrefermoulepointeurnulencasderreur.
Enfin,lamthode is_open permetdedterminersiunfichierestouvertounondanscetampon.
Exemple152.Lectureetcrituredansuntampondefichier
#include <iostream>
#include <string>
#include <fstream>
usingnamespacestd;
intmain(void)
{
//Ouvreunfichiertexteetcreuntamponpouryaccder:
filebuffb;
fb.open("test.txt",ios_base::in|ios_base::out|ios_base::trunc);
//Testesilefichierestouvert:
if(fb.is_open())
{
//critdeuxlignes:
stringl1="Bonjour\n";
stringl2="toutlemonde!\n";
fb.sputn(l1.data(),l1.size());
fb.sputn(l2.data(),l2.size());
//Repositionnelepointeurdefichieraudbut.
//Note:ledplacementsefaitpourlesdeux
//tamponsparcequilnyaquunpointeur
//surlesdonnesdufichier:
fb.pubseekpos(0,ios_base::in|ios_base::out);
//Litlespremireslettresdufichier:
cout << (char)fb.sbumpc() << endl;
cout << (char)fb.sbumpc() << endl;
cout << (char)fb.sbumpc() << endl;
//Fermelefichier:
fb.close();
}
return0;
}

289

Chapitre15.Lesfluxdentre/sortie

15.3.Lesclassesdebasedesflux:ios_baseet
basic_ios
Lesclassesdegestiondesfluxconstituentladeuximehirarchiedeclassesdelabibliothquestan
darddentre/sortie.Bienquedestinesaccderdesmdiasvaris,cesclassesdisposentdune
interfacecommunequipermetdensimplifierlutilisation.Cetteinterfaceestessentiellementdfinie
pardeuxclassesdebasesfondamentales:laclasseios_base, quidfinittouteslesfonctionnalits
template basic_ios,quiregroupe
indpendantesdutypedecaractreutilisparlesflux,etlaclasse
lessentieldesfonctionnalitsdesfluxdentre/sortie.

15.3.1.Laclasseios_base
Laclasseios_baseest uneclasseC++classiquedont touteslesclasses template degestiondes
fluxdentre/sortiedrivent. Cetteclassenefournit, commecestlecasdelaplupartdesclasses
debase,quunnombredefonctionnalitstrsrduit.Enpratique,saprincipaleutilitestdedfinir
plusieursjeuxdeconstantesquisontutilisesparsesclassesdrivespouridentifierlesoptionsdes
diffrentsmodesdefonctionnementdisponibles.Cesconstantesportentunnomstandardismaisleur
typenestpasprcisparlanormeC++.Cependant,leurnature(entire,numration,champdebits)
estimpose,etlesimplmentationsdoiventdfinirun typedef permettantdecrerdesvariablesdu
mmetype.
Laclassedebaseios_baseestdclarecommesuitdanslentte ios :
classios_base
{
//Constructeuretdestructeur:
protected:
ios_base();
public:
~ios_base();
//Classedebasedesexceptionsdesfluxdentre/sortie:
classfailure;
//Classedinitialisationdesobjetsdentre/sortiestandards:
classInit;
//Constantesdedfinitiondesoptionsdeformatage:
typedefT1fmtflags;
staticconstfmtflagsboolalpha;
staticconstfmtflagshex;
staticconstfmtflagsoct;
staticconstfmtflagsdec;
staticconstfmtflagsfixed;
staticconstfmtflagsscientific;
staticconstfmtflagsleft;
staticconstfmtflagsright;
staticconstfmtflagsinternal;
staticconstfmtflagsshowbase;
staticconstfmtflagsshowpoint;
staticconstfmtflagsshowpos;
staticconstfmtflagsuppercase;
staticconstfmtflagsunitbuf;
staticconstfmtflagsskipws;

290

Chapitre15.Lesfluxdentre/sortie
staticconstfmtflagsadjustfield;
staticconstfmtflagsbasefield;
staticconstfmtflagsfloatfield;
//Constantesdesmodesdouverturedesfluxetdesfichiers:
typedefT3openmode;
staticconstopenmodein;
staticconstopenmodeout;
staticconstopenmodebinary;
staticconstopenmodetrunc;
staticconstopenmodeapp;
staticconstopenmodeate;
//Constantesdedfinitiondesmodesdepositionnement:
typedefT4seekdir;
staticconstseekdirbeg;
staticconstseekdircur;
staticconstseekdirend;
//Constantesdtatdesfluxdentre/sortie:
typedefT2iostate;
staticconstiostategoodbit;
staticconstiostateeofbit;
staticconstiostatefailbit;
staticconstiostatebadbit;
//Accesseurssurlesoptionsdeformatage:
fmtflagsflags()const;
fmtflagsflags(fmtflagsfmtfl);
fmtflagssetf(fmtflagsfmtfl);
fmtflagssetf(fmtflagsfmtfl,fmtflagsmask);
voidunsetf(fmtflagsmask);
streamsizeprecision()const;
streamsizeprecision(streamsizeprec);
streamsizewidth()const;
streamsizewidth(streamsizewide);
//Mthodedesynchronisation:
staticboolsync_with_stdio(boolsync=true);
//Mthodedenregistrementdescallbackpourlesvnements:
enumevent{erase_event,imbue_event,copyfmt_event};
typedefvoid(*event_callback)(event,ios_base&,intindex);
voidregister_callback(event_call_backfn,intindex);
//Mthodedegestiondesdonnesprives:
staticintxalloc();
long&iword(intindex);
void*&pword(intindex);
//Mthodesdegestiondeslocales:
localeimbue(constlocale&loc);
localegetloc()const;
};

291

Chapitre15.Lesfluxdentre/sortie
Commevouspouvezleconstater,leconstructeurdelaclasseios_baseestdclarenzoneprotge.
Ilnestdoncpaspossibledinstancierunobjetdecetteclasse,
cequiestnormalpuisquellenest
destinequtrelaclassedebasedeclassesplusspcialises.
Lepremierjeudeconstantesdfiniparlaclasseios_basecontienttouteslesvaleursdetypefmtflags,
quipermettentdespcifierlesdiffrentesoptionsutiliserpourleformatagedesdonnescritesdans
lesflux.Cetypedoitobligatoirementtreunchampdebits.Lesconstantesquantellespermettent
dedfinirlabasedenumrotationutilise,sicellecidoittreindiqueavecchaquenombreounon,
ainsiquelesdiffrentesoptionsdeformatageutiliser. Lasignificationprcisedechacunedeces
constantesestdonnedansletableausuivant:
Tableau151.Optionsdeformatagedesflux
Constante

292

Signification

boolalpha

Permetderaliserlesentres/sortiesdesboolenssousformetextuelleetnon
sousformenumrique.Ainsi,lesvaleurs true et false nesontpascritesou
luessouslaformede 0 oude 1,maissouslaformefixeparlaclassede
localisationutiliseparleflux.Pardfaut,lesboolenssontreprsentsparles
chanesdecaractrestrueetfalselorsqueceflagestactif.Cependant,il
estpossibledemodifierceschanesdecaractresendfinissantunelocale
spcifique.LesnotionsdelocalesserontdcritesdansleChapitre16.

hex

Permetderaliserlesentres/sortiesdesentiersenbasehexadcimale.

oct

Permetderaliserlesentres/sortiesdesentiersenbaseoctale.

dec

Permetderaliserlesentres/sortiesdesentiersendcimal.

fixed

Activelareprsentationenvirgulefixedesnombresvirguleflottante.

scientific

Activelareprsentationenvirguleflottantedesnombresvirguleflottante.

left

Utiliselalignementgauchepourlesdonnescritessurlesfluxdesortie.
Danslecasolalargeurdeschampsestfixe,descaractresderemplissage
sontajoutsladroitedecesdonnespouratteindrecettelargeur.

right

Utiliselalignementdroitepourlesdonnescritessurlesfluxdesortie.
Danslecasolalargeurdeschampsestfixe,descaractresderemplissage
sontajoutslagauchedecesdonnespouratteindrecettelargeur.

internal

Effectueunremplissageaveclescaractresderemplissageunepositionfixe
dtermineparlalocaleencoursdutilisationsilalargeurdesdonnesest
infrieurelalargeurdeschampsutiliser.Silapositionderemplissagenest
passpcifieparlalocalepourloprationencours,lecomportementadopt
estlalignementdroite.

showbase

Prciselabaseutilisepourleformatagedesnombresentiers.

showpoint

critsystmatiquementlesparateurdelavirguledansleformatagedes
nombresvirguleflottante,quelapartiefractionnairedecesnombressoit
nulleounon.Lecaractreutilispourreprsentercesparateurestdfinidans
lalocaleutiliseparlefluxdentre/sortie.Lanotiondelocaleseravuedans
leChapitre16.Pardfaut,lecaractreutilisestlepointdcimal(.).

showpos

Utilisesystmatiquementlesignedesnombrescritssurlefluxdesortie,
quilssoientpositifsoungatifs.Leformatagedusignedesnombresefait
selonlescritresdfinisparlalocaleactivepourceflux.Pardfaut,les
nombresngatifssontprfixsdusymbole etlesnombrespositifsdu
symbole +sicetteoptionestactive.Danslecascontraire,lesignedes
nombrespositifsnestpascrit.

Chapitre15.Lesfluxdentre/sortie
Constante

Signification

uppercase

edelexposant
Permetdcrireenmajusculecertainscaractres,commele
desnombresvirguleflottanteparexemple,ouleschiffreshexadcimaux A
F.

unitbuf

Permetdeffectuerautomatiquementuneoprationdesynchronisationdu
cacheutilisparlefluxdesortieaprschaquecriture.

skipws

Permetdignorerlesblancsprcdantlesdonnesliredanslesoprations
dentrepourlesquellesdetelsblancssontsignificatifs.

Laclasseios_basedfinitgalementlesconstantes adjustfield, basefield et floatfield,qui


sontenralitdescombinaisonsdesautresconstantes.Ainsi,laconstante adjustfield reprsente
lensembledesoptionsdalignement(savoir left, right et internal),laconstante basefield
reprsentelesoptionsdespcificationdebasepourlessortiesnumriques(cestdirelesoptions
hex, oct et dec), etlaconstante floatfield lesoptionsdfinissantlestypesdeformatagedes
nombresvirgules( scientific et fixed).
Ledeuximejeudeconstantespermetdecaractriserlesmodesdouverturedesfluxetdesfichiers.
Letypedecesconstantesestletypeopenmode.Ilsagitgalementdunchampdebits,cequipermet
deraliserdescombinaisonsentreleursvaleurspourcumulerdiffrentsmodesdouverturelorsde
lutilisationdesfichiers.Lesconstantesdfiniesparlaclasseios_basesontdcritesdansletableau
cidessous:
Tableau152.Modesdouverturedesfichiers
Constante

Signification

in

Permetdouvrirlefluxencriture.

out

Permetdouvrirlefluxenlecture.

binary

Permetdouvrirlefluxenmodebinaire,pourlessystmesquifontune
distinctionentrelesfichierstextesetlesfichiersbinaires.Ceflagnestpas
ncessairepourlessystmesdexploitationconformeslanormePOSIX.
Cependant,ilestprfrabledelutiliserlorsdelouverturedefichiersbinaires
silonveutqueleprogrammesoitportablesurlesautressystmes
dexploitation.

trunc

Permetdeviderautomatiquementlefichierlorsquuneouvertureencritureest
demande.

app

Permetdouvrirlefichierenmodeajoutlorsquuneouvertureencritureest
demande.Danscemode,lepointeurdefichierestsystmatiquement
positionnenfindefichieravantchaquecriture.Ainsi,lescrituressefontles
uneslasuitedesautres,toujourslafindufichier,etquellesquesoientles
oprationsquipeuventavoirlieusurlefichierentretemps.

ate

Permetdouvrirlefichierencritureetdepositionnerlepointeurdefichierla
findeceluici.Notezquecemodedefonctionnementsedistinguedumode
app parlefaitquesiunrepositionnementalieuentredeuxcrituresla
deuximecritureneseferapasforcmentlafindufichier.

Letroisimejeudeconstantesdfinit lesdiversesdirectionsquil est possibledutiliserlorsdun


repositionnementdunpointeurdefichier.Letypedecesconstantes,savoirletypeseekdir,estune
numrationdontlesvaleurssontdcritesdansletableaucidessous:

293

Chapitre15.Lesfluxdentre/sortie
Tableau153.Directionsdedplacementdansunfichier
Constante

Signification

beg

Ledplacementdefaitparrapportaudbutdufichier.Ledcalagespcifi
danslesfonctionsderepositionnementdoittrepositifounul,lavaleur0
correspondantaudbutdufichier.

cur

Ledplacementsefaitrelativementlapositioncourante.Ledcalagespcifi
danslesfonctionsderepositionnementpeutdonctrengatif,positifounul
(auquelcasaucundplacementnesteffectu).

end

Ledplacementsefaitrelativementlafindufichier.Ledcalagefournidans
lesfonctionsderepositionnementdoittrepositifounul,lavaleur0
correspondantlafindefichier.

Enfin, lesconstantesdetypeiostatepermettent dedcrirelesdiffrentstatsdanslequel unflux


dentre/sortiepeutsetrouver.Ilsagit,encoreunefois,dunchampdebits,etplusieurscombinai
sonssontpossibles.
Tableau154.tatsdesfluxdentre/sortie
Constante

Signification

goodbit

Cetteconstantecorrespondltatnormalduflux,lorsquilnesestproduit
aucuneerreur.

eofbit

Cebitestpositionndanslavariabledtatdufluxlorsquelafindufluxat
atteinte,soitparcequilnyaplusdedonneslire,soitparcequonnepeut
plusencrire.

failbit

Cebitestpositionndanslavariabledtatdufluxlorsquuneerreurlogique
sestproduitelorsduneoprationdelectureoudcriture.Cecipeutavoirlieu
lorsquelesdonnescritesouluessontincorrectes.

badbit

Cebitestpositionnlorsquuneerreurfatalesestproduite.Cegenrede
situationpeutseproduirelorsquuneerreuraeulieuauniveaumatriel
(secteurdfectueuxdundisqueduroucoupurerseauparexemple).

Lesdiffrentesvariablesdtat desfluxdentre/ sortiepeuvent tremanipuleslaidedeces


constantesetdesaccesseursdelaclasseios_base.Lesmthodeslesplusimportantessontsansdoute
cellesquipermettentdemodifierlesoptionsdeformatagepourlefluxdentre/sortie.Lamthode
flags permetdercuprerlavaleurdelavariabledtatcontenantlesoptionsdeformatageduflux.
Cettemthodedisposegalementdunesurchargequipermetdespcifierunenouvellevaleurpour
cettevariabledtat,etquiretournelavaleurprcdente.Ilestaussipossibledefixeretdedsactiver
lesoptionsdeformatageindpendammentlesunesdesautreslaidedesmthodes setf et unsetf.
Lamthode setf prendenparamtrelesnouvellesoptionsquidoiventtreajoutesaujeudoptions
djactives,avec,ventuellement,unmasquepermettantderinitialisercertainesautresoptions.On
emploieragnralementunmasquelorsquelonvoudrafixerunparamtreparmiplusieursparamtres
mutuellementexclusifs,commelabasedenumrotationutiliseparexemple.Lamthode unsetf
prendquantellelemasquedesoptionsquidoiventtresupprimesdujeudoptionsutilisparle
fluxenparamtre.
Outrelesmthodesdegestiondesoptionsdeformatage,laclasseios_basedfinitdeuxsurcharges
pourchacunedesmthodes precision et width.Cesmthodespermettentrespectivementdelire
etdefixerlaprcisionaveclaquellelesnombresvirguledoiventtrecritsetlalargeurminimale

294

Chapitre15.Lesfluxdentre/sortie
desconversionsdesnombreslorsdescritures.
Laplupartdesoptionsquelonpeutfixersontpermanentes,cestdirequellesrestentactivesjus
qucequonspcifiedenouvellesoptions.Cependant,cenestpaslecasduparamtredelargeur
quelonrenseignegrcelamthode width. Eneffet, chaqueoprationdcriturerinitialisece
paramtrelavaleur0.Ilfautdoncspcifierlalargeurminimalepourchaquedonnecritesurle
flux.
Exemple153.Modificationdesoptionsdeformatagedesflux
#include <iostream>
usingnamespacestd;
//Afficheunboolen,unnombreentieretunnombrevirgule:
voidprint(boolb,inti,floatf)
{
cout << b << "" << i << "" << f << endl;
}
intmain(void)
{
//Afficheaveclesoptionspardfaut:
print(true,35,3105367.9751447);
//Passeenhexadcimal:
cout.unsetf(ios_base::dec);
cout.setf(ios_base::hex);
print(true,35,3105367.9751447);
//Affichelabasedesnombreset
//affichelesboolenstextuellement:
cout.setf(ios_base::boolalpha);
cout.setf(ios_base::showbase);
print(true,35,3105367.9751447);
//Afficheunflottantennotationvirgulefixe
//avecunelargeurminimalede16caractres:
cout << "***";
cout.width(16);
cout.setf(ios_base::fixed,ios_base::floatfield);
cout << 315367.9751447;
cout << "***" << endl;
//Recommenceenfixantlaprcision
//3chiffresetlalargeur10caractres:
cout << "***";
cout.precision(3);
cout.width(10);
cout << 315367.9751447;
cout << "***" << endl;
return0;
}
Note:Onprendrabiengardeaufaitquelalargeurdeschampsdanslesquelslesdonnessont
critesestunelargeurminimale,pasunelargeurmaximale.Enparticulier,celasignigiequeles
crituresnesontpastronquessiellessontplusgrandequecettelargeur.Ondevradoncfaire
extrmementattentionnepasprovoquerdedbordementslorsdescritures.
Onnoublierapasdesassurerdelacohrencedesparamtresdufluxlorsquonmodifielavaleur
duneoption.Parexemple,danslexempleprcdent,ilfautdsactiverlemploi delanumrota
tiondcimalelorsquelondemandeutiliserlabasehexadcimale.Cetteoprationatfaite

295

Chapitre15.Lesfluxdentre/sortie
explicitementici pourbienmontrersonimportance,maiselleauraitgalementputreralise
parlemploidunmasqueaveclaconstante ios_base::basefield .Lexempleprcdentmon
trecommentutiliserunmasqueaveclappel setf pourfixerlareprsentationdesnombres
virgule.

Laclasseios_basefournitgalementuncertainnombredeservicesgnrauxauprogrammeuret
sesclassesdrives.Lamthode sync_with_stdio permetdedterminer,pourunfluxdentre/
sortiestandard,silestsynchronisaveclefluxsousjacentousidesdonnessetrouventencoredans
sontampon.Lorsquelleestappeleavecleparamtre false dsledbutduprogramme,ellepermet
dedcorrlerlefonctionnementdufluxC++etdufluxstandardsousjacent.Pourtouslesautresap
pels,cettemthodeignoreleparamtrequiluiestfourni.Lamthode register_callback permet
denregistrerunefonctionderappelquiseraappeleparlaclasseios_baselorsquedesvnements
susceptiblesdemodifiernotablementlecomportementdufluxseproduisent.Cesfonctionsderappel
peuventrecevoirunevaleurentireenparamtrequipeuttreutilisepourrfrencerdesdonnes
privescontenantdesparamtrespluscomplexes.Lesmthodesxalloc, iword et pword sontfour
niesafindepermettredestockercesdonnespriveset delesretrouverfacilement laidedun
indice,quipeuttrelavaleurpasseenparamtrelafonctionderappel.Cesmthodespermettent
dercuprerdesrfrencessurdesvaleursdetypelongetsurdespointeursdetypevoid.Enfin,la
classeios_basefournituneclassedebasepourlesexceptionsquelesclassesdefluxpourrontutiliser
cin, cout, cerr, clog et
afindesignaleruneerreuretuneclassepermettantdinitialiserlesobjets
leurssemblablespourlescaractreslarges.Toutescesfonctionnalitsnesontgnralementpasdune
trsgrandeutilitpourlesprogrammeursetsontenralitfourniepourfaciliterlimplmentationdes
classesdefluxdelabibliothquestandard.
Enfin, laclasseios_basefournitlesmthodes getloc et imbue quipermettentrespectivementde
rcuprerlalocaleutiliseparlefluxet
denfixeruneautre. Cettelocaleest utiliseparleflux
pourdterminerlamaniredereprsenteretdelirelesnombresetpoureffectuerlesentres/sorties
formatesenfonctiondesparamtresdelangueetdesconventionslocalesdupaysoleprogramme
est excut. Lesnotionsdelocaleet deparamtresinternationauxseront dcritsendtail dansle
Chapitre16.

15.3.2.Laclassebasic_ios
Laclasse template basic_iosfournittouteslesfonctionnalitscommunestouteslesclassesde
fluxdelabibliothquedentre/sortie.Cetteclassedrivedelaclasseios_baseetapportetousles
mcanismesdegestiondestamponspourlesclassesdeflux.Laclassebasic_iosestdclarecomme
suitdanslentte ios :
template <classcharT,
classtraits=char_traits
<charT>>
classbasic_ios:publicios_base
{
//Constructeuretdestructeur:
protected:
basic_ios();
voidinit(basic_streambuf
<charT,traits> *flux);
public:
//Typesdedonnes:
typedefcharT
char_type;
typedeftypenametraits::int_typeint_type;
typedeftypenametraits::pos_typepos_type;

296

Chapitre15.Lesfluxdentre/sortie
typedeftypenametraits::off_typeoff_type;
typedeftraits
traits_type;
//Constructeurpublique,destructeuretoprationdecopie:
explicitbasic_ios(basic_streambuf
<charT,traits> *flux);
virtual~basic_ios();
basic_ios&copyfmt(constbasic_ios&);
//Mthodesdegestiondestampons:
basic_streambuf<charT,traits> *rdbuf()const;
basic_streambuf<charT,traits> *rdbuf(
basic_streambuf<charT,traits> *tampon);
//Mthodesdegestiondesexceptions:
iostateexceptions()const;
voidexceptions(iostateexcept);
//Accesseurs:
operatorvoid*()const
booloperator!()const
iostaterdstate()const;
voidclear(iostatestatut=goodbit);
voidsetstate(iostatestatut);
boolgood()const;
booleof() const;
boolfail()const;
boolbad() const;
char_typefill()const;
char_typefill(char_typec);
basic_ostream<charT,traits> *tie()const;
basic_ostream<charT,traits> *tie(
basic_ostream<charT,traits> *flux);
//Mthodesdegestiondeslocales:
localeimbue(constlocale&loc);
char
narrow(char_typec,chardefaut)const;
char_typewiden(charc)const;
};

Leconstructeurdebaseainsiquelamthode init,destineassocieruntamponunfluxaprssa
construction,sontdclarsenzoneprotge.Ainsi,ilnestpaspossibledinstancieretdinitialiser
manuellementunfluxavecuntampon.Cependant,laclassebasic_iosfournitunconstructeurenzone
publiquequi permet decrerunnouveaufluxet delinitialiserlavole. Ceconstructeurprend
enparamtreladresseduntamponquiseraassociaufluxaprslaconstruction.Remarquezque,
bienquil soit ainsi parfaitement possibledinstancierunobjet detypelunedesinstancesdela
classe template basic_ios,celanapasgrandintrt.Eneffet,cetteclassenefournitpasassezde
fonctionnalitspourraliserdesentres/sortiesfacilementsurleflux.Laclassebasic_iosestdonc
rellementdestinetreutiliseentantqueclassedebasepourdesclassesplusspcialisesdans
lesoprationsdentre/sortie.
Unefoisinitialiss,lesfluxsontassocisauxtamponsgrceauxquelsilsaccdentauxmdiasphy
siquespourleursoprationsdentre/sortie. Cependant, cetteassociationnestpasfigeetilest
possibledechangerdetamponaposteriori. Lesmanipulationsdetamponsonteffectuesavecles
deuxsurchargesdelamthode rdbuf.Lapremirepermetdercuprerladressedelobjettampon

297

Chapitre15.Lesfluxdentre/sortie
courantetladeuximedenspcifierunnouveau.Cettederniremthoderenvoieladressedutampon
prcdent.Bienentendu,lefaitdechangerletampondunfluxprovoquesarinitialisation.
Lesfluxdelabibliothquestandardpeuventsignalerlescasderreursauxfonctionsquilesutilisentde
diffrentesmanires.Lapremireestsimplementderenvoyeruncodederreur(false oulecaractre
defindefichier),etladeuximeestdelanceruneexceptiondrivedelaclassedexceptionfailure
(dfiniedanslaclassedebaseios_base). Cecomportementestparamtrableenfonctiondestypes
derreursquipeuventseproduire.Pardfaut,lesclassesdefluxnutilisentpaslesexceptions,quelles
quesoientleserreursrencontres. Toutefois, ilestpossibledactiverlemcanismedesexceptions
individuellementpourchaquetypederreurpossible.Laclassebasic_iosgrepourcelaunmasque
dexceptionsquipeuttrercupretmodifilaidededeuxmthodessurcharges.Cesmthodes
sontlesmthodes exceptions.Lapremireversionrenvoielemasquecourantetladeuximepermet
defixerunnouveaumasque.Lesmasquesdexceptionssontconstitusdecombinaisonslogiquesdes
bitsdtatdesfluxdfinisdanslaclasseios_base(savoirgoodbit, eofbit, failbit et badbit).
Lefaitdechangerlemasquedexceptionsrinitialiseltatduflux.
Laclassebasic_iosfournitgalementtoutunensembledaccesseursgrceauxquelsilestpossiblede
rcuprerltatcourantduflux.Cesaccesseurssontprincipalementdestinsfaciliterlamanipulation
dufluxetsimplifierlesdiffrentesexpressionsdanslesquellesilestutilis.Parexemple,loprateur
detranstypageversletypepointeursurvoidpermetdetesterlavaliditdufluxcommesilsagissait
dunpointeur.Cetoprateurretourneeneffetunevaleurnonnullesilefluxestutilisable(cestdire
silamthode fail renvoie false.Demme,loprateurdengation operator! renvoielamme
valeurquelamthode fail.
Commevouslaurezsansdoutecompris, lamthode fail indiquesi leflux(et doncletampon
true dsquelun
contrlparceflux)estdansuntatcorrect.Enpratique,cettemthoderenvoie
desbits ios_base::failbit ou ios_base::badbit estpositionndanslavariabledtatduflux.
Vouspourrezfaireladistinctionentrecesdeuxbitsgrcelamthode bad,quiellenerenvoie true
quesilebit ios_base::badbit estpositionn. Lesautresmthodesdelecturedeltatduflux
portentdesnomsexplicitesetleursignificationnedoitpasposerdeproblme.Onprendratoutefois
gardebiendistinguerlamthode clear,quipermetderinitialiserltatdufluxaveclemasquede
bitspassenparamtre,delamthode setstate,quipermetdepositionnerunbitcomplmentaire.
Cesdeuxmthodessontsusceptiblesdelancerdesexceptionssilenouveltatdufluxlerequiertetsi
sonmasquedexceptionslexige.
Ledernieraccesseurutilepourleprogrammeurestlaccesseur fill. Cetaccesseurpermetdelire
lavaleurducaractrederemplissageutilislorsquelalargeurdeschampsestsuprieurelalargeur
desdonnesqui doivent trecritessurlefluxdesortie. Pardfaut, cecaractreest lecaractre
despacement.
Note:Lesdeuxsurchargesdelamthodetie permettentdestockerdanslefluxunpointeursur
unfluxdesortiestandardaveclequellesoprationsdentre/sortiedoiventtresynchronises.
Cesmthodessontutiliseseninterneparlesmthodesdentre/sortiedesclassesdrives
delaclassebasic_iosetnesontpasrellementutilespourlesprogrammeurs.Engnraldonc,
seulelesclassesdelabibliothquestandardlesappelleront.

Enfin,laclassebasic_iosprendgalementencomptelalocaledufluxdanstoussestraitements.Elle
redfinitdonclamthode imbue afindepouvoirdtecterleschangementdelocalequelutilisateur
peutfaire.Bienentendu,lamthode getloc esthritedelaclassedebaseios_baseetpermettou
joursdercuprerlalocalecourante.Deplus,laclassebasic_iosdfinitdeuxmthodespermettant
deraliserlesconversionsentreletypedecaractrecharetletypedecaractrefournienparamtre
template.Lamthode widen permet,commesonnomlindique,deconvertiruncaractredetype
char enuncaractredutype template duflux.Inversement,lamthodenarrow permetdeconver

298

Chapitre15.Lesfluxdentre/sortie
tiruncaractredutypedecaractredufluxenuncaractredetypechar.
Cettemthodeprenden
paramtrelecaractreconvertiretlavaleurpardfautquedoitprendrelersultatencasdchecde
laconversion.

15.4.Lesfluxdentre/sortie
Laplupart desfonctionnalitsdesfluxdentre/ sortiesont implmentesauniveaudesclasses
template basic_ostreametbasic_istream.Cesclassesdriventtoutesdeuxdirectementdelaclasse
basic_ios,dontelleshritentdetouteslesfonctionnalitsdegestiondestamponsetdegestiondtat.
Lesclassesbasic_ostreametbasic_istreamserontsansdoutelesclassesdefluxquevousutiliserezle
plussouvent,carcestleurniveauquesontdfiniestouteslesfonctionnalitsdelectureetdcriture
surlesflux,aussibienpourlesdonnesformatestellesquelesentiers,lesflottantsouleschanesde
caractres,quepourlescrituresdedonnesbrutes.Deplus,lesfluxdentre/sortiestandards cin,
cout, cerr et clog sonttousdesinstancesdecesclasses.
Labibliothquestandarddfinitgalementuneclassecapablederaliserlafoislesoprationsde
lectureetdcrituresurlesflux:laclassebasic_iostream.Enfait,cetteclassedrivesimplementdes
deuxclassesbasic_istreametbasic_ostream,etregroupedonctouteslesfonctionnalitsdecesdeux
classes.

15.4.1.Laclassedebasebasic_ostream
Laclassebasic_ostreamfournittouteslesfonctionspermettantdeffectuerdescrituressurunflux
desortie, quecescrituressoient formatesounon. Elleest dclarecommesuit danslentte
ostream :
template <classcharT,
classtraits=char_traits
<charT>>
classbasic_ostream:virtualpublicbasic_ios<charT,traits>
{
public:
//Lestypesdedonnes:
typedefcharT
char_type;
typedeftypenametraits::int_typeint_type;
typedeftypenametraits::pos_typepos_type;
typedeftypenametraits::off_typeoff_type;
typedeftraits
traits_type;
//Leconstructeuretledestructeur:
explicitbasic_ostream(basic_streambuf
<char_type,traits> *tampon);
virtual~basic_ostream();
//Lesoprationsdcrituresformates:
basic_ostream<charT,traits> &operator<<(bool);
basic_ostream<charT,traits> &operator<<(short);
basic_ostream<charT,traits> &operator<<(unsignedshort);
basic_ostream<charT,traits> &operator<<(int);
basic_ostream<charT,traits> &operator<<(unsignedint);
basic_ostream<charT,traits> &operator<<(long);
basic_ostream<charT,traits> &operator<<(unsignedlong);
basic_ostream<charT,traits> &operator<<(float);
basic_ostream<charT,traits> &operator<<(double);

299

Chapitre15.Lesfluxdentre/sortie
basic_ostream<charT,traits> &operator<<(longdouble);
basic_ostream<charT,traits> &operator<<(void*);
basic_ostream<charT,traits> &operator<<
(basic_streambuf<char_type,traits> *tampon);
//Classedegestiondesexceptionspourlesoprateursdcrituresformates:
classsentry
{
public:
explicitsentry(basic_ostream
<charT,traits> &);
~sentry();
operatorbool();
};
//Lesoprationsdcrituresnonformates:
basic_ostream<charT,traits> &put(char_type);
basic_ostream<charT,traits> &write(constchar_type*p,streamsizetaille);
//Lesoprationsdegestiondutampon:
basic_ostream<charT,traits> &flush();
pos_typetellp();
basic_ostream<charT,traits> &seekp(pos_type);
basic_ostream<charT,traits> &seekp(off_type,ios_base::seekdir);
//Lesoprationsdegestiondesmanipulateurs:
basic_ostream<charT,traits> &operator<<
(basic_ostream<charT,traits> &(*pf)(
basic_ostream<charT,traits> &));
basic_ostream<charT,traits> &operator<<
(basic_ios<charT,traits> &(*pf)(basic_ios <charT,traits> &));
basic_ostream<charT,traits> &operator<<
(ios_base&(*pf)(ios_base&));
};

Commevouspouvezleconstater, leconstructeurdecetteclasseprendenparamtreunpointeur
surlobjettampondanslequellescrituresdevronttreralises. Vouspouvezdoncconstruireun
fluxdesortiepartirdenimportequeltampon,simplementenfournissantcetamponenparamtre
auconstructeur. Cependant, ilnefautpasprocderainsiengnral, maisutiliserpluttlesclasses
drivesdelaclassebasic_ostreametspcialisesdanslescrituressurfichiersetdansdeschanes
decaractres.
Lescrituresformatessont ralisesparlintermdiairedediffrentessurchargesdeloprateur
dinsertion operator<<,dontilexisteuneversionpourchaquetypededonnedebasedulangage.
Ainsi,lcrituredunevaleurdanslefluxdesortiesefaitextrmementsimplement:
//crituredunechanedecaractressurlefluxdesortiestandard:
cout << "Voicilavaleurdunentier:\n";
//crituredunentiersurlefluxdesortiestandard:
cout << 45;

Vousconstaterezque, grceauxmcanismesdesurcharge, cescrituressefont


mmemanirepourtouslestypesdedonnes.Onnepeutfaireplussimple...

300

exactement dela

Chapitre15.Lesfluxdentre/sortie
Note:Lesoprationsdeformatageprennentencomptetouteslesoptionsdeformatagequisont
stockesdanslaclassedebaseios_base.Engnral,lesoprationsdcriturenemodifientpas
cesoptions.Toutefois,lalargeurminimaledeschampsdanslesquelslesrsultatssontformats
estsystmatiquementrinitialise0aprschaquecriture.Ilestdoncncessaire,lorsquelon
raliseplusieurscrituresformatesdansunfluxdesortie,despcifierpourchaquevaleursa
largeurminimalesiellenedoitpastregale0.Autrementdit,ilfautredirelalargeurdechaque
champ,mmesilsutilisenttouslammelargeurminimale.
Lesoprationsdeformatageutilisentgalementlesconventionslocalesdupaysoleprogramme
estexcut,conventionsquisontdfiniesdanslalocaleinclusedanslefluxdesortie.Lesnotions
delocaleserontdtaillesdansleChapitre16.

Bienentendu, ilestpossiblededfinirdenouvellessurchargesdeloprateurdinsertionpourles
typesdfinisparlutilisateur, cequipermetdtendrelinfinilespossibilitsdecetteclasse.
Ces
surchargesdevrontobligatoirementtredfinieslextrieurdelaclasse template basic_ostream
template
et,silonveutlescriredemaniregnrique,ellesdevrontgalementtredesfonctions
paramtresparletypedecaractredufluxsurlequelellestravaillent.
Vousnoterezlaprsenceduneclassesentrydanslaclassebasic_ostream.Cetteclasseestuneclasse
utilitairepermettantderaliserlesinitialisationsquidoiventprcdertouteslesoprationsdcriture
auseindessurchargesdeloprateurdinsertion. Entreautresoprations, leconstructeurdecette
tie
classepeut synchroniserlefluxdesortiestandardencapsuldanslefluxgrcelamthode
delaclassedebasebasic_ios, et prendretouteslesmesuresdevant prcderlescrituressurle
flux.Vousdevrezdonctoujoursutiliserunobjetlocaldecetypelorsquevouscrirezunesurcharge
deloprateur operator<< pourvosproprestypes. Lescrituresnedevronttreralisesquesi
linitialisationarussi,cequipeuttrevrifisimplementencomparantlobjetlocaldetypesentry
aveclavaleur true.
Exemple154.Dfinitiondunnouveloprateurdinsertionpourunfluxdesortie
#include <iostream>
#include <string>
usingnamespacestd;
//Dfinitionduntypededonnepriv:
structPersonne
{
stringNom;
stringPrenom;
intAge;
//Encentimtres.
intTaille;
};
//Dfinitiondeloprateurdcriturepourcetype:
template <classcharT,classTraits
>
basic_ostream<charT,Traits> &operator<<(
basic_ostream<charT,Traits> &flux,
constPersonne&p)
{
//Inialisationdufluxdesortie:
typenamebasic_ostream<charT,Traits>::sentryinit(flux);
if(init)
{
//crituredesdonnes:

301

Chapitre15.Lesfluxdentre/sortie
intMetres=p.Taille/100;
intReste=p.Taille%100;
flux << p.Prenom << "" << p.Nom <<
"mesure" << Metres <<
"m" << Reste << "(" <<
p.Age << "an";
if(p.Age > 1)flux << "s";
flux << ")";
}
returnflux;
}
intmain(void)
{
//Construitunenouvellepersonne:
Personnep;
p.Nom="Dupont";
p.Prenom="Jean";
p.Age=28;
p.Taille=185;
//Affichelescaractristiquesdecettepersonne:
cout << p << endl;
return0;
}
Note:Lutilisationdelobjetlocal detypesentrycommeunboolenestautoriseparcequela
classesentrydfinitunoprateurdetranstypageversletypebool.
Leconstructeurdelaclassesentryestsusceptibledelancerdesexceptions,selonlaconfigura
tiondumasquedexceptionsdufluxdesortieaveclequelonlinitialise.

Lescrituresdedonnesbrutesnedisposentbienentendupasdesurchargespourchaquetypede
donne,puisquilsagitdanscecasdcrirelesdonnesdirectementsurlefluxdesortie,sanslesfor
matersousformetextuelle.Cescrituressontdoncralisesparlintermdiairedemthodesddies
qui effectuent soit lcritureduncaractreunique, soit lcritureduntableaudecaractrescom
plet.Pourcrireununiquecaractresurlefluxdesortie,vouspouvezutiliserlamthode put.Pour
lcrituredunblocdedonnesenrevanche,ilfaututiliserlamthode write,quiprendenparamtre
unpointeursurlazonededonnescrireetlatailledecettezone.
Exemple155.criturededonnesbrutessurunfluxdesortie
#include <iostream>
usingnamespacestd;
//Dfinitiondequelquescodesdecouleurs
//pourlesterminauxANSI:
constcharRouge[]={033,[,3,1,m};
constcharVert[]={033,[,3,2,m};
constcharJaune[]={033,[,3,3,m};
constcharReset[]={033,[,m,017};
intmain(void)
{
//crituredunmessagecolor:
cout.write(Rouge,sizeof(Rouge));

302

Chapitre15.Lesfluxdentre/sortie
cout << "Bonjour";
cout.write(Vert,sizeof(Vert));
cout << "tout";
cout.write(Jaune,sizeof(Jaune));
cout << "lemonde!" << endl;
cout.write(Reset,sizeof(Reset));
return0;
}

Bienentendu,laclassebasic_ostreamfournitlesmthodesncessaireslagestiondutamponsous
jacent.Lamthode flush permetdesynchroniserletamponutilisparleflux(enappelantlamthode
pubsync decedernier).Lamthode tellp permetdelirelapositioncourantedanslefluxdesortie,
etlesdeuxsurchargesdelamthode seekp permettentdemodifiercettepositionsoitdemanire
absolue,soitdemanirerelativelapositioncourante.Nousverronsunexempledutilisationdeces
mthodesdansladescriptiondesclassesdefluxpourlesfichiers.
Laclassebasic_ostreamdfinit galement dessurchargesdeloprateur dinsertioncapablesde
prendreenparamtredespointeursdefonctions. Cesmthodesneconstituent pasdesoprations
dcritureproprementparler,maispermettentderaliserdesoprationssurlesfluxdesortieplus
facilementlaidedefonctionscapablesdelesmanipuler.Enraisondecetteproprit,cesfonctions
sontcourammentappelesdesmanipulateurs.Enralit,cesmanipulateursnesontriendautreque
desfonctionsprenant unfluxenparamtreet ralisant desoprationssurceflux. Lesoprateurs
operator<< prenant enparamtrecesmanipulateurslesexcutent
sur lobjet courant *this.
Ainsi,ilestpossibledappliquercesmanipulateursunfluxsimplementenralisantunecrituredu
manipulateursurceflux,exactementcommepourlescrituresnormales.
Labibliothquestandarddfinit tout unjeudemanipulateursextrmement utilespourdfinirles
optionsdeformatageetpoureffectuerdesoprationsdebasesurlesflux.Grcecesmanipulateurs,
ilnestplusncessairedutiliserlamthode setf delaclasseios_baseparexemple.Parexemple,le
symbole endl utilispoureffectuerunretourlalignedanslesoprationsdcrituresurlesfluxde
sortienestriendautrequunmanipulateur,dontladclarationestlasuivante:
template <classcharT,classTraits
>
basic_ostream<charT,Traits> &endl(
basic_ostream<charT,Traits> &flux);

etdontlerleestsimplementdcrirelecaractrederetourlaligneetdappelerlamthode flush
dufluxdesortie.
Ilexistedesmanipulateurspermettantdetravaillersurlaclassedebaseios_baseousursesclasses
drivescommelaclassebasic_ostreamparexemple, dolaprsencedeplusieurssurchargesde
loprateurdinsertionpourcesdiffrentsmanipulateurs.Ilexistegalementdesmanipulateurspre
nantdesparamtresetrenvoyantuntypededonnesspcialpourlequelunoprateurdcritureat
dfini,etquipermettentderaliserdesoprationspluscomplexesncessitantdesparamtrescom
plmentaires.Lesmanipulateurssontdfinis,selonleurnature,soitdanslenttededclarationdu
flux,soitdanslentte ios,soitdanslentte iomanip.
Letableausuivantprsentelesmanipulateurslesplussimplesquineprennentpasdeparamtre:
Tableau155.Manipulateursdesfluxdesortie
Manipulateur

Fonction

endl

Envoieuncaractrederetourlalignesurlefluxetsynchroniseletamponpar
unappellamthode flush.

ends

Envoieuncaractrenulterminaldefindelignesurleflux.

303

Chapitre15.Lesfluxdentre/sortie
Manipulateur

Fonction

flush

Synchroniseletamponutilisparlefluxparunappellelamthode

boolalpha

flush.

Activeleformatagedesboolenssousformetextuelle.

noboolalpha

Dsactiveleformatagetextueldesboolens.

hex

Formatelesnombresenbase16.

oct

Formatelesnombresenbase8.

dec

Formatelesnombresenbase10.

fixed

Utiliselanotationenvirgulefixepourlesnombresvirgule.

scientific

Utiliselanotationenvirguleflottantepourlesnombresvirgule.

left

Alignelesrsultatsgauche.

right

Alignelesrsultatsdroite.

internal

Utiliseleremplissagedeschampsavecdesespacescomplmentairesune
positionfixedtermineparlalocalecourante.quivalent right silalocale
nespcifieaucunepositionderemplissageparticulire.

showbase

Indiquelabasedenumrotationutilise.

noshowbase

Nindiquepaslabasedenumrotationutilise.

showpoint

Utiliselesparateurdevirguledanslesnombresvirgule,mmesilapartie
fractionnaireestnulle.

noshowpoint

Nutiliselesparateurdevirgulequesilapartiefractionnairedesnombres
virguleflottanteestsignificative.

showpos

critsystmatiquementlesignedesnombres,mmesilssontpositifs.

noshowpos

Ncritlesignedesnombresquesilssontngatifs.

uppercase

critlesexposantsetleschiffreshexadcimauxenmajuscule.

nouppercase

critlesexposantsetleschiffreshexadcimauxenminuscule.

unitbuf

Effectueuneoprationdesynchronisationducachegrparletamponduflux
aprschaquecriture.

nounitbuf

Neffectuelesoprationsdesynchronisationducachegrparletampondu
fluxquelorsquecelaestexplicitementdemand.

Lesparamtressuivantssontunpeupluscomplexes,puisquilsprennentdesparamtrescomplmen
taires.Ilsrenvoientuntypededonnespcifiquechaqueimplmentationdelabibliothquestandard
etquinestdestinqutreinsrdansunfluxdesortielaidedeloprateurdinsertion:
Tableau156.Manipulateursutilisantdesparamtres
Manipulateur

304

Fonction

resetiosflags(ios_base::fmtflags)

Permetdeffacercertainsbitsdesoptionsdu
flux.Cesbitssontspcifisparunecombinaison
logiquedeconstantesdetypeios_base::fmtflags.

setiosflags(ios_base::fmtflags)

Permetdepositionnercertainsbitsdesoptions
duflux.Cesbitssontspcifisparune
combinaisonlogiquedeconstantesdetype
ios_base::fmtflags.

Chapitre15.Lesfluxdentre/sortie
Manipulateur

Fonction

setbase(intbase)

Permetdeslectionnerlabasedenumrotation
utilise.Lesvaleursadmissiblessont8,10et16
respectivementpourlabaseoctale,labase
dcimaleetlabasehexadcimale.

setprecision(int)

Permetdespcifierlaprcision(nombrede
caractressignificatifs)desnombresformats.

setw(int)

Permetdespcifierlalargeurminimaledu
champdanslequelladonnesuivanteseracrite
laprochaineoprationdcrituresurleflux.

setfill(char_type)

Permetdespcifierlecaractrederemplissage
utiliserlorsquelalargeurdeschampsest
infrieurelalargeurminimalespcifiedans
lesoptionsdeformatage.

Exemple156.Utilisationdesmanipulateurssurunfluxdesortie
#include <iostream>
#include <iomanip>
usingnamespacestd;
intmain(void)
{
//Affichelesboolenssousformetextuelle:
cout << boolalpha << true << endl;
//critlesnombresenhexadcimal:
cout << hex << 57 << endl;
//Repasseenbase10:
cout << dec << 57 << endl;
//Afficheunflottantavecunelargeur
//minimalede15caractres:
cout << setfill(*) << setw(15) << 3.151592 << endl;
//Recommencemaisavecunalignementgauche:
cout << left << setw(15) << 3.151592 << endl;
}

15.4.2.Laclassedebasebasic_istream
La deuxime classe la plus utilise de la bibliothque dentre / sortie est sans doute la
classe template basic_istream. linstar de la classe ostream, cette classe fournit toutes
lesfonctionnalitsdelecturededonnesformatesounonpartir
duntampon. Cesont donc
certainementlesmthodescetteclassequevousutiliserezleplussouventlorsquevousdsirerezlire
lesdonnesdunflux.Laclassebasic_istreamestdclarecommesuitdanslentteistream :
template <classcharT,
classtraits=char_traits
<charT>>
classbasic_istream:virtualpublicbasic_ios<charT,traits>
{
public:

305

Chapitre15.Lesfluxdentre/sortie
//Lestypesdedonnes:
typedefcharT
char_type;
typedeftypenametraits::int_typeint_type;
typedeftypenametraits::pos_typepos_type;
typedeftypenametraits::off_typeoff_type;
typedeftraits
traits_type;
//Leconstructeuretdestructeur:
explicitbasic_istream(basic_streambuf
<charT,traits> *sb);
virtual~basic_istream();
//Lesoprationdegestiondesentresformates:
basic_istream<charT,traits> &operator>>(bool&n);
basic_istream<charT,traits> &operator>>(short&n);
basic_istream<charT,traits> &operator>>(unsignedshort&n);
basic_istream<charT,traits> &operator>>(int&n);
basic_istream<charT,traits> &operator>>(unsignedint&n);
basic_istream<charT,traits> &operator>>(long&n);
basic_istream<charT,traits> &operator>>(unsignedlong&n);
basic_istream<charT,traits> &operator>>(float&f);
basic_istream<charT,traits> &operator>>(double&f);
basic_istream<charT,traits> &operator>>(longdouble&f);
basic_istream<charT,traits> &operator>>(void*&p);
basic_istream<charT,traits> &operator>>
(basic_streambuf<char_type,traits> *sb);
//Classedegestiondesexceptionspourlesoprateursdcrituresformates:
classsentry
{
public:
explicitsentry(basic_istream
<charT,traits> &flux,
boolconserve=false);
~sentry();
operatorbool();
};
//Lesoprationsdelecturedesdonnesbrutes:
int_typeget();
basic_istream<charT,traits> &get(char_type&c);
int_typepeek();
basic_istream<charT,traits> &putback(char_typec);
basic_istream<charT,traits> &unget();
basic_istream<charT,traits> &read(char_type*s,streamsizen);
streamsize
readsome(char_type*s,streamsizen);
basic_istream<charT,traits> &get(char_type*s,streamsizen);
basic_istream<charT,traits> &get(char_type*s,streamsizen,
char_typedelim);
basic_istream<charT,traits> &get(
basic_streambuf<char_type,traits> &sb);
basic_istream<charT,traits> &get(
basic_streambuf<char_type,traits> &sb,char_typedelim);
basic_istream<charT,traits> &getline(char_type*s,streamsizen);
basic_istream<charT,traits> &getline(char_type*s,streamsizen,
char_typedelim);
basic_istream<charT,traits> &ignore
(streamsizen=1,int_typedelim=traits::eof());

306

Chapitre15.Lesfluxdentre/sortie

streamsizegcount()const;
//Lesoprationsdegestiondutampon:
intsync();
pos_typetellg();
basic_istream<charT,traits> &seekg(pos_type);
basic_istream<charT,traits> &seekg(off_type,ios_base::seekdir);
//Lesoprationsdegestiondesmanipulateurs:
basic_istream<charT,traits> &operator>>
(basic_istream<charT,traits> &(*pf)(
basic_istream<charT,traits> &));
basic_istream<charT,traits> &operator>>
(basic_ios<charT,traits> &(*pf)(basic_ios <charT,traits> &));
basic_istream<charT,traits> &operator>>
(ios_base&(*pf)(ios_base&));
};

Toutcommelaclassebasic_ostream,leconstructeurdelaclassebasic_istreamprendenparamtre
unpointeursurlobjetgrantletampondanslequellescrituresdevronttreeffectues.Cependant,
mmesilestpossibledecreruneinstancedefluxdentresimplementlaidedececonstructeur,
celanestpasrecommandpuisquelabibliothquestandardfournitdesclassesspcialisespermet
tantdecrerdesfluxdesortieorientsfichiersouchanesdecaractres.
Lutilisation des diffrentes surcharges de loprateur dextraction des donnes formates
operator>> nedevraitpasposerdeproblme.Lecompilateurdterminelasurchargeutiliseren
fonctiondutypedesdonneslire, dterminparlarfrencedevariablefournieenparamtre.
Cettesurchargercuprealorslesinformationsdansletamponassociauflux,lesinterprteetcrit
lanouvellevaleurdanslavariable.
Bienentendu, tout commepourlaclassebasic_ostream, il est possibledcriredenouvellessur
chargesdeloprateurdextractionafindeprendreenchargedenouveauxtypesdedonnes.Idale
ment,cessurchargesdevronttregalementdesfonctions template paramtresparletypedeca
ractredufluxsurlequelellestravaillent,etellesdevrontgalementutiliseruneclassedinitialisation
sentry.Cetteclasseaprincipalementpourbutdinitialiserlefluxdentre,ventuellementenlesyn
chronisantavecunfluxdesortiestandarddontlaclassebasic_ostreampeuttrestockedansleflux
dentrelaidedelamthode tie delaclassedebasebasic_ios, etensupprimantlesventuels
caractresblancsavantlalecturedesdonnes.
Notezque,contrairementlaclassesentrydesfluxdesortie,leconstructeurdelaclassesentrydes
fluxdentreprendundeuximeparamtre.Ceparamtreestunboolenquiindiquesilescaractres
blancsprsentsdanslefluxdedonnesdoiventtreliminsavantloprationdelectureounon.En
gnral, pourlesoprationsdelectureformates, cesontdescaractresnonsignificatifsetilfaut
effecivementsupprimercescaractres,aussilavaleurspcifierpourcesecondparamtreestelle
false. Commecest aussi lavaleurpardfaut, lamaniredutiliserdelaclassesentrydansles
oprateursdextractioneststrictementidentiquecelledelaclassesentrydesoprateursdinsertion
delaclassebasic_ostream.
Exemple157.crituredunnouveloprateurdextractionpourunfluxdentre
#include <iostream>
#include <string>

307

Chapitre15.Lesfluxdentre/sortie
usingnamespacestd;
//Dfinitionduntypededonnepriv:
structPersonne
{
stringNom;
stringPrenom;
intAge;
//Encentimtres.
intTaille;
};
//Dfinitiondeloprateurdelecturepourcetype:
template <classcharT,classTraits
>
basic_istream<charT,Traits> &operator>>(
basic_istream<charT,Traits> &flux,Personne&p)
{
//Inialisationdufluxdesortie:
typenamebasic_istream<charT,Traits>::sentryinit(flux);
if(init)
{
//Lectureduprnometdunom:
flux >> p.Prenom;
flux >> p.Nom;
//Lecturedelge:
flux >> p.Age;
//Lecturedelatailleenmtres:
doubleTaille;
flux >> Taille;
//Conversionencentimtres;
p.Taille=(int)(Taille*100+0.5);
}
returnflux;
}
intmain(void)
{
//Construitunenouvellepersonne:
Personnep;
//Demandelasaisiedunepersonne:
cout << "PrnomNomge(ans)Taille(m):";
cin >> p;
//Affichelesvaleurslues:
cout << endl;
cout << "Valeurssaisies:" << endl;
cout << p.Prenom << "" << p.Nom << "a"
<<
p.Age << "ansetmesure"
<<
p.Taille << "cm." << endl;
return0;
}
Note:Laclassesentryest galement utiliseparlesmthodesdelecturededonnesnon
formates.Pourcesmthodes,lescaractresblancssontimportantsetdanscecaslesecond
true.
paramtrefourniauconstructeurdelaclassesentryest
Commepourlaclassesentrydelaclassebasic_ostream, lutilisationdelobjet dinitialisation
danslestestsest renduepossibleparlaprsencedeloprateurdetranstypageversletype
bool.Lavaleurretourneesttrue silinitialisationsestbienfaiteet false danslecascontraire.

308

Chapitre15.Lesfluxdentre/sortie
Remarquezgalement queleconstructeurdelaclassesentryest susceptibledelancerdes
exceptionsselonlaconfigurationdumasquedexceptionsdanslaclassedeflux.

Lesoprationsdelecturededonnesnonformatessontunpeuplusnombreusespourlesfluxdentre
quelesoprationsdcriturenonformatespourlesfluxdesortie.Eneffet,laclassebasic_istream
donnenonseulementlapossibilitdelireuncaractresimpleouunesriedecaractres,maisausside
lirelesdonnesprovenantdutampondelectureetdelesinterprterentantquelignes.Uneligne
estenralitunesriedecaractrestermineparuncaractrespcialquelonnommelemarqueur
defindeligne.Engnral,cemarqueurestlecaractre\n,maisilestpossibledespcifierunautre
caractre.
Lalectureduncaractreuniquedanslefluxdentresefaitlaidedelamthodeget.Ilexistedeux
surchargesdecettemthode,lapremireneprenantaucunparamtreetrenvoyantlecaractrelu,et
ladeuximeprenantenparamtreunerfrencesurlavariabledevantrecevoirlecaractreluetne
renvoyantrien.Cesdeuxmthodesextraientlescaractresquelleslisentdutampondentrequele
fluxutilise.Silonveutsimplementlirelavaleurducaractresuivantsanslenextraire,ilfautappeler
lamthode peek.Deplus,toutcaractreextraitpeuttrerinsrdanslefluxdentre(pourvuquele
tamponsousjacentacceptecetteopration)laidedelunedesdeuxmthodes unget ou putback.
Cettederniremthodeprendenparamtrelecaractrequidoittrerinsrdanslefluxdentre.
Notezquelarinsertionnepeuttreralisequesilecaractrefournienparamtreestprcisment
lederniercaractreextrait.
Silondsireraliserlalecturedunesriedecaractresaulieudelesextraireunun,ilfaututiliser
lamthode read.Cettemthodeestlamthodedebasepourleslecturesnonformatespuisquellelit
lesdonnesbrutesdefonderie,sanslesinterprter.Elleprendenparamtreunpointeursuruntableau
decaractresdanslequellesdonnesserontcritesetlenombredecaractreslire.Cettemthode
nevrifiepaslatailledutableauspcifi,aussiceluicidoitiltrecapabledaccueillirlenombrede
caractresdemand.Ilexisteunevariantedelamthoderead,lamthode readsome,quipermetde
lirelesdonnesprsentesdansletampongrparlefluxsansaccderaumdiaquecedernierprend
encharge. Cettemthodeprendgalement enparamtreunpointeursurlazonemmoiredevant
recevoirlesdonnesetlenombredecaractresdsir,mais,contrairementlamthode read,elle
peutnepaslireexactementcenombre.Eneffet,lamthode readsome sarrtedsqueletampon
utilisparlefluxestvide,cequipermetdviterlesaccssurlepriphriqueauquelcetampondonne
accs.Lamthode readsome renvoielenombredecaractreseffectivementlus.
Lesmthodesdelecturedeslignessontdiviserendeuxcatgories.Lapremirecatgorie,constitue
deplusieurssurchargesdelamthode get, permetdeffectuerunelecturedesdonnesdutampon
jusqucequeletableaufourni enparamtresoit rempli ouquunefindelignesoit atteinte. La
deuximecatgoriedemthodesestconstituedessurchargesdelamthodegetline.Cesmthodes
sedistinguentdesmthodes get parlefaitquellesnchouentpaslorsquelalignelue(dlimiteurde
lignecompris)remplitcompltementletableaufournienparamtredunepart,etparlefaitquele
dlimiteurdeligneestextraitdutampondentreutilisparlefluxdautrepart.Autrementdit,siune
lignecomplte(cestdireavecsondlimiteur)aunetailleexactementgalelatailledutableau
fournienparamtre,lesmthodes get chouerontalorsquelesmthodes getline russiront,car
ellesneconsidrentpasledlimiteurcommeuneinformationimportante.Cecirevientdirequeles
mthodes getline interprtentcompltementlecaractredlimiteur,alorsquelesmthodes get le
traitentsimplementcommelecaractreauquellalecturedoitsarrter.
Danstouslescas,uncaractrenulterminalestinsrenlieuetplacedudlimiteurdansletableau
fournienparamtreetdevantrecevoirlesdonnes.Commeledeuximeparamtredecesmthodes
indiqueladimensiondecetableau,lenombredecaractresluestaupluscettedimensionmoinsun.
Lenombredecaractresextraitsdutampondentreestquantluircuprablegrcelamthode
gcount.Remarquezquelecaractredefindeligneestcomptdanslenombredecaractresextraits

309

Chapitre15.Lesfluxdentre/sortie
pourlesmthodes getline,alorsquilnelestpaspourlesmthodes get puisquecesderniresne
lextraientpasdutampon.
Enfin,ilestpossiblededemanderlalectureduncertainnombredecaractresetdelespassersans
enrcuprerlavaleur. Cetteoprationestralisablelaidedelamthode ignore, quineprend
doncpasdepointeurssurlazonemmoireolescaractreslusdoiventtrestockspuisquilssont
ignors.Cettemthodelitautantdecaractresquespcifi,saufsilecaractredlimiteurindiquen
deuximeparamtreestrencontr.Danscecas,cecaractreestextraitdutampondentre,cequifait
quelamthode ignore secomporteexactementcommelesmthodes getline.
Exemple158.Lecturesdelignessurlefluxdentrestandard
#include <iostream>
#include <sstream>
usingnamespacestd;
intmain(void)
{
//Tableaudevantrecevoiruneligne:
charpetit_tableau[10];
//Litunelignede9caractres:
cout << "Saisissezuneligne:" << endl;
cin.getline(petit_tableau,10);
if(cin.fail())
cout << "Lignetroplongue!" << endl;
cout << "Lu:***" << petit_tableau << "***" << endl;
//Litunelignedetaillearbitraireviauntampon:
cout << "Saisissezuneautreligne:" << endl;
stringbufs;
cin.get(s);
//Affichelalignelue:
cout << "Lu:***" << s.str() << "***";
//Extraitlecaractredesautdeligne
//etajouteleaufluxdesortiestandard:
cout << (char)cin.get();
return0;
}
Note:Remarquezquelecaractredesaut delignetant lu, il est ncessairedesaisirdeux
retoursdechariot successifspourquelamthode getline renvoiesonrsultat. Commepour
touteslesmthodesdelecturesformates,cecaractreinterromptlalecturedanslefluxdentre
standardduprogrammeet setrouvedoncencoredansletampondentrelorsdelalecture
suivante.Celaexpliquequedanslecasdelecturessuccessives,il fautextrairececaractredu
fluxdentremanuellement,parexemplelaidedelamthode get.Cestcequecetexemple
ralisesursadernirelignepourlenvoyersurlefluxdesortiestandard.
Deplus,onnepeutpasprvoir,apriori,quelleseralatailledeslignessaisiesparlutilisateur.
Onneprocderadoncpascommeindiqudanscetexemplepoureffectuerlalecturedelignes
enpratique. Il est eneffet plusfaciledutiliser lafonction getline, quelonadcrit dansla
Section14.1.8danslecadredutypebasic_string.Eneffet,cettefonctionpermetdelireuneligne
compltesansavoirsesoucierdesalongueurmaximaleet destockerlersultat dansune
basic_string.

310

Chapitre15.Lesfluxdentre/sortie
Laclassebasic_istreamdisposegalementdemthodespermettantdemanipulerletamponquelle
utilisepourliredenouvellesdonnes.Lamthode sync permetdesynchroniserletampondentre
aveclemdiaauquelildonneaccs, puisquelleappellelamthode pubsync decetampon. Pour
lesfluxdentre,celanapasrellementdimportanceparcequelonnepeutpascrirededans.La
mthode tellg permetdedterminerlapositiondupointeurdelecturecourant,etlesdeuxsurcharges
delamthode seekg permettentderepositionnercepointeur.Nousverronsunexempledutilisation
decesmthodesdansladescriptiondesclassesdefluxpourlesfichiers.
Enfin,lesfluxdentredisposentgalementdequelquesmanipulateurspermettantdelesconfigurer
simplementlaidedeloprateur operator>>.Cesmanipulateurssontprsentsdansletableau
cidessous:
Tableau157.Manipulateursdesfluxdentre
Manipulateur

Fonction

boolalpha

Activelinterprtationdesboolenssousformedetextuelle.

noboolalpha

Dsactivelinterprtationdesboolenssousformetextuelle.

hex

Utiliselabase16pourlinterprtationdesnombresentiers.

oct

Utiliselabase8pourlinterprtationdesnombresentiers.

dec

Utiliselabase10pourlinterprtationdesnombresentiers.

skipws

Ignorelesespaceslorsdesentresformates.

noskipws

Conservelesespaceslorsdesentresformates.

ws

Supprimetouslesespacesprsentsdanslefluxdentrejusquau
premiercaractrenonblanc.

Cesmanipulateurssutilisentdirectementlaidedeloprateur operator>>,exactementcomme
lesmanipulateursdelaclassebasic_ostreamsutilisentavecloprateurdinsertionnormal.

15.4.3.Laclassebasic_iostream
Labibliothquestandarddfinitdanslentte iostream laclasse template basic_iostreamafin
depermettrelafoislesoprationsdcritureetlesoprationsdelecturesurlesflux.Enfait,cette
classenestriendautrequuneclassedrivedesdeuxclassesbasic_ostreametbasic_istreamqui
fournissentrespectivement,commeonlavu,touteslesfonctionnalitsdelectureetdcrituresurun
tampon.
Laclassebasic_iostreamnecomportepasdautresmthodesquunconstructeuretundestructeur,
quiserventuniquementinitialiseretdtruirelesclassesdebasebasic_ostreametbasic_istream.
Lutilisationdecetteclassenedoitdoncpasposerdeproblmeparticulieretjevousinvitevous
rfrerauxdescriptionsdesclassesdebasesibesoinest.
Note:Toutcommesesclassesdebase,laclassebasic_iostreamserararementutilisedirecte
ment. Eneffet, elledisposedeclassesdrivesspcialisesdanslesoprationsdcritureet
delecturesurfichiersoudansdeschanesdecaractres,classesquelonprsenteradansles
sectionssuivantes.Cesontcesclassesquelonutiliseraenpratiquelorsquelondsireracrer
unnouveaufluxpourlireetcriredansunfichieroudansunebasic_string.
Vousaurezpeuttreremarququelesclassesbasic_ostreamet
basic_istreamutilisent un
hritagevirtuel pourrcuprerlesfonctionnalitsdelaclassedebasebasic_ios.Laraisonen
est quelaclassebasic_iostreamraliseunhritagemultiplesursesdeuxclassesdebaseet
quelesdonnesdelaclassebasic_iosnedoiventtreprsentequenunseulexemplairedans
lesfluxdentre/sortie.Celaimpliquequelesconstructeursdesclassesdrivesdelaclasse

311

Chapitre15.Lesfluxdentre/sortie
basic_iostreamprenantdesparamtresdoiventappelerexplicitementlesconstructeursdetoutes
leurclassesdebase.VoyezlaSection8.6pourplusdedtailssurlesnotionsdhritagemultiple
etdeclassesvirtuelles.

15.5.Lesfluxdentre/sortiesurchanesde
caractres
Afindedonnerlapossibilitauxprogrammeursdeffectuerlesoprationsdeformatagedesdonnes
enmmoireaussisimplementquaveclesclassesdegestiondesfluxdentre/sortiestandards,
la
bibliothquedentre/sortiedfinittroisclassesdefluxcapablesdetravaillerdansdeschanesde
caractresdetypebasic_string. Cesclassessontlesclassesbasic_ostringstream, pourlescritures
dansleschanesdecaractres, basic_istringstream, pourleslecturesdedonnesstockesdansles
chanesdecaractres,etbasic_stringstream,pourlesoprationslafoisdcritureetdelecture.
Ces classes drivent respectivement des classes de flux basic_istream, basic_ostreamet
basic_iostreametreprennentdoncleurcomptetouteslesfonctionsdeformatageetdcriturede
cesclasses. Lescrituresetleslecturesdedonnesenmmoiresefontdonc,
grcecesclasses,
aussi facilement quavecles fluxdentre/ sortiestandards, et cedemanirecompltement
transparente.
Enfait, lesclassesdefluxorienteschanesdecaractresfonctionnent
exactement commeleurs
classesdebase,cartouteslesfonctionnalitsdegestiondeschanesdecaractressontencapsulesau
niveaudesclassesdegestiondestamponsquionttprsentesaudbutdecechapitre.Cependant,
ellesdisposentdemthodesspcifiquesquipermettentdemanipulerleschanesdecaractressur
lesquellesellestravaillent.Parexemple,laclassebasic_ostringstreamestdclarecommesuitdans
lentte sstream :
template <classcharT,
classtraits=char_traits
<charT>,
classAllocator=allocator
<charT>>
classbasic_ostringstream:publicbasic_ostream
<charT,traits>
{
public:
//Lestypesdedonnes:
typedefcharT
char_type;
typedeftypenametraits::int_typeint_type;
typedeftypenametraits::pos_typepos_type;
typedeftypenametraits::off_typeoff_type;
//Lesconstructeursetdestructeurs:
explicitbasic_ostringstream(ios_base::openmodemode=ios_base::out);
explicitbasic_ostringstream(
constbasic_string<charT,traits,Allocator> &chaine,
ios_base::openmodemode=ios_base::out);
virtual~basic_ostringstream();
//Lesmthodesdegestiondelachanedecaractres:
basic_stringbuf<charT,traits,Allocator
> *rdbuf()const;
basic_string<charT,traits,Allocator
> str()const;
void
str(constbasic_string<charT,traits,Allocator
> &chaine);
};

312

Chapitre15.Lesfluxdentre/sortie
Lesclassesbasic_istringstreametbasic_stringstreamsontdclaresdemanireidentique,ceciprs
quelesclassesdebaseetlesvaleurspardfautpourlesmodesdouverturedutamponsurlachane
decaractresnesontpaslesmmes.
Commevouspouvezleconstater,ilestpossibledeconstruireunfluxdentre/sortiesurunechane
decaractresdediffrentesmanires.Lapremiremthodeestdeconstruireunobjetflux,puisde
prciser,pourlesfluxdentre,lachanedecaractresdanslaquellelesdonnesliresetrouvent
laidedelamthode str.Ladeuximemthodeesttoutsimplementdefournirtouslesparamtres
enuneseulefoisauconstructeur.Engnral,lesvaleurspardfautspcifiesdanslesconstructeurs
correspondentcequelonveutfaireaveclesflux, cequifaitquelaconstructiondecesfluxest
extrmementsimple.
Unefoisconstruit, ilestpossiblederalisertouteslesoprationsquelondsiresurleflux.
Dans
lecasdesfluxdentre, ilestncessairequelefluxaittinitialisavecunechanedecaractres
contenantlesdonneslire,etlonnecherchegnralementpasrcuprercettechaneaprsusage
duflux.Pourlesfluxdesortie,cetteinitialisationestinutile.Enrevanche,lersultatdesoprations
deformatageseragnralementrcuprlaidedelamthode str unefoiscellesciralises.
Exemple159.Utilisationdefluxdentre/sortiesurchanesdecaractres
#include <iostream>
#include <sstream>
#include <string>
usingnamespacestd;
intmain(void)
{
//Lituneligneenentre:
cout << "EntierRelChane:";
stringinput;
getline(cin,input);
//Interprtelalignelue:
istringstreamis(input);
inti;
doubled;
strings;
is >> i >> d;
is >> ws;
getline(is,s);
//Formatelarponse:
ostringstreamos;
os << "Larponseest:"
<< endl;
os << s << "" << 2*i << "" << 2*d << endl;
//Affichelachanedelarponse:
cout << os.str();
return0;
}

Commelexempleprcdentvouslemontre,lutilisationdesfluxdentre/sortiedelabibliothque
standardsurleschanesdecaractresestrellementaise. Commecesoprationsnepeuventtre
ralisesquenmmoire, cest direendehorsducontextedusystmedexploitationutilis,
les
classesdefluxdelabibliothquerestentutilesmmesilesoprationsdentre/sortiedusystmese
fontdetellemanirequelesobjets cin et cout nesontpratiquementpasutilisables.

313

Chapitre15.Lesfluxdentre/sortie

15.6.Lesfluxdentre/sortiesurfichiers
Lesclassesdentre/ sortiesurlesfichierssont implmentesdemaniresimilaireauxclasses
dentre/sortiesurleschanesdecaractres,ceciprsqueleursmthodesspcifiquespermettent
demanipulerunfichieraulieudunechanedecaractres.Ainsi,laclassebasic_ofstreamdrivede
basic_ostream, laclassebasic_ifstreamdelaclassebasic_istream, etlaclassebasic_fstreamdela
classebasic_iostream. Toutescesclassessontdclaresdanslentte fstream. Voustrouverez
titredexempleladclarationdelaclassebasic_ofstreamtelquilapparatdanscetentte:
template <classcharT,
classtraits=char_traits
<charT>>
classbasic_ofstream:publicbasic_ostream <charT,traits>
{
public:
//Lestypesdedonnes:
typedefcharT
char_type;
typedeftypenametraits::int_typeint_type;
typedeftypenametraits::pos_typepos_type;
typedeftypenametraits::off_typeoff_type;
//Lesconstructeursetdestructeurs:
basic_ofstream();
explicitbasic_ofstream(constchar*nom,
ios_base::openmodemode=ios_base::out|ios_base::trunc);
//Lesmthodesdegestiondufichier:
basic_filebuf<charT,traits> *rdbuf()const;
boolis_open();
voidopen(constchar*nom,ios_base::openmodemode=out|trunc);
voidclose();
};

Commepourlesfluxdentre/sortiesurleschanesdecaractres,ilestpossibledinitialiserleflux
dssaconstructionouaposteriori. Lesmthodesimportantessontbienentendulamthode open,
quipermetdouvrirunfichier,lamthode is_open,quipermetdesavoirsilefluxcontientdjun
fichierouvertounon,etlamthode close,quipermetdefermerlefichierouvert.
Exemple1510.Utilisationdefluxdentre/sortiesurunfichier
#include <iostream>
#include <fstream>
#include <string>
usingnamespacestd;
intmain(void)
{
//Litlesdonnes:
inti;
doubled,e;
cout << "EntierRelRel:";
cin >> i >> d >> e;
//Enregistrecesdonnesdansunfichier:
ofstreamf("fichier.txt");
if(f.is_open())

314

Chapitre15.Lesfluxdentre/sortie
{
f << "Lesdonnesluessont:"
<<
i << "" << d << "" << e << endl;
f.close();
}
return0;
}
Note:Ilestimportantdebiennoterqueledestructeurdesfluxnefermepaslesfichiers.Eneffet,
cesontlestamponsutilissdemaniresousjacenteparlesfluxquiralisentlesoprationssur
lesfichiers.Ilestmmetoutfaitpossibledaccderunmmefichieravecplusieursclassesde
flux,bienquecelanesoitpasfranchementrecommand.Vousdevrezdoncprendreencharge
vousmmelesoprationsdouvertureetdefermeturedesfichiers.

Bienentendu,lesclassesdefluxpermettantdaccderdesfichiershritentdesmthodesdeposition
nementdeleursclassesdebase.Ainsi,lesclassesdelecturedansunfichierdisposentdesmthodes
tellg et seekg,etlesclassesdcrituredisposentdesmthodes tellp et seekp.Cesoprations
permettentrespectivementdelireetdefixerunenouvellevaleurdupointeurdepositiondufichier
courant.
Exemple1511.Repositionnementdupointeurdefichierdansunfluxdentre/sortie
#include <iostream>
#include <fstream>
#include <string>
usingnamespacestd;
intmain(void)
{
//Ouvrelefichierdedonnes:
fstreamf("fichier.txt",
ios_base::in|ios_base::out|ios_base::trunc);
if(f.is_open())
{
//critlesdonnes:
f << 2 << "" << 45.32 << "" << 6.37 << endl;
//Replacelepointeurdefichieraudbut:
f.seekg(0);
//Litlesdonnes:
inti;
doubled,e;
f >> i >> d >> e;
cout << "Lesdonnesluessont:" <<
i << "" << d << "" << e << endl;
//Fermelefichier:
f.close();
}
return0;
}
Note:Lesclassesdentre/ sortiesurfichiernutilisent quunseul tamponpouraccderaux
fichiers. Parconsquent, il nexistequuneseulepositiondanslefichier, qui sert lafoisla
lectureetlcriture.

315

Chapitre15.Lesfluxdentre/sortie

316

Chapitre16.Leslocales
Il existedenombreuxalphabetset denombreusesmaniresdcrirelesnombres, lesdateset les
montantsdepartlemonde.Chaquepays,chaqueculturedisposeeneffetdesespropresconventions
etdesespropresrgles,etcedansdenombreuxdomaines.Parexemple,lesAnglosaxonsontpour
coutumedutiliserlepoint(caractre .)poursparerlesunitsdelavirgulelorsquilscriventdes
nombresvirguleetdutiliserunevirgule(caractre ,)entrechaquegroupedetroischiffrespour
sparerlesmilliersdesmillions,lesmillionsdesmilliards,etc.EnFrance,cestlavirguleestutilise
poursparerlesunitsdelapartiefractionnairedesnombresvirgule,etlesparateurdesmilliers
estsimplementunespace.Demme,ilsontlhabitudedcrirelesdatesenmettantlemoisavantles
jours,alorsquelesFranaisfontlinverse.
Ilvadesoiquecegenredediffrencesrendtechniquementtrsdifficilelinternationalisationdes
programmes.Unesolutionesttoutsimplementdedirequelesprogrammestravaillentdansunelangue
neutre,cequienpratiquerevientsouventdirelanglaispuisquecestlalanguehistoriquement
laplusutiliseeninformatique.Hlas,sicelaconvenaitparfaitementauxprogrammeurs,ceneserait
certainement paslecasdesutilisateurs!Il faut donc, unmoment donnouunautre, queles
programmesprennentencomptelesconventionslocalesdechaquepaysoudechaquepeuple.
Cesconventionssontextrmementnombreusesetportentsurdesdomainesaussidiversetvarisque
lamaniredcrirelesnombres,lesdatesoudecoderlescaractresetdeclasserlesmotsdansun
dictionnaire.Eninformatique,ilestcourantdappelerlensembledesconventionsdunpayslalocale
decepays.Lesprogrammesquiprennentencomptelalocalesontdoncditslocalissetsontcapables
desadapterauxprfrencesnationalesdelutilisateur.
Note:Lefaitdtrelocalisnesignifiepaspourautantpourunprogrammequetoussesmes
sagessont traduitsdanslalanguedelutilisateur. Lalocalisationneprendencomptequeles
aspectsconcernantlcrituredesnombresetlesalphabetsutiliss.Afindebienfairecettedis
tinction,onditquelesprogrammescapablesdecommuniqueraveclutilisateurdanssalangue
sont internationaliss.Laconversiondunprogrammedunpaysunautrencessitedoncla
foislalocalisationdeceprogrammeetsoninternationalisation.

Silatraductiondetouslesmessagesdunprogrammenepeutpastreraliseautomatiquement,il
esttoutefoispossibledeprendreencompteleslocalesrelativementfacilement. Eneffet, lesfonc
tionnalitsdesbibliothquesCet C++, enparticulierlesfonctionnalitsdentre/ sortie, peuvent
gnralement treparamtresparlalocaledelutilisateur.
Lagestiondeslocalesest donccom
pltementpriseenchargeparcesbibliothquesetunmmeprogrammepeutdonctreutilissans
modificationdansdiverspays.
Note:Enrevanche, latraductiondesmessagesnepeut bienvidemment pastrepriseen
chargeparlabibliothquestandard,saufventuellementpourlesmessagesderreurdusystme.
Laralisationdunprogrammeinternationalncessitedoncdeprendredesmesuresparticulires
pourfaciliterlatraductiondecesmessages. Engnral, cesmesuresconsistent isolerles
messagesdansdesmodulesspcifiqueset nepaslesutiliserdirectement danslecodedu
programme.Ainsi,il suffitsimplementdetraduirelesmessagesdecesmodulespourajouterle
support dunenouvellelangueunprogrammeexistant. Lecodesourcenaainsi pastre
touch,cequilimitelesrisquesderreurs.

LagestiondeslocalesenC++sefaitparlintermdiaireduneclassegnrale,laclasselocale,qui
permetdestockertouslesparamtreslocauxdespays.Cetteclasseestbienentenduutiliseparles
fluxdentre/ sortiedelabibliothquestandard, cequi fait quevousnaurezgnralement qu

317

Chapitre16.Leslocales
initialisercetteclasseaudbut devosprogrammespourleurfaireprendreencompteleslocales.
Cependant, ilsepeutquevousayezmanipulervousmmedeslocalesoudfinirdenouvelles
conventionsnationales,surtoutsivouscrivezdessurchargesdesoprateursdeformatagedesflux
operator<< et operator>>.Cechapitreprsentedonclesnotionsgnralesdeslocales,lesdif
frentesclassesmisesenoeuvreauseindunemmelocalepourprendreenchargetouslesaspectsde
lalocalisation,etlamanirededfinirouderedfinirundecesaspectsafindecomplterunelocale
existante.

16.1.Notionsdebaseetprincipedefonctionnement
desfacettes
Commeillatditplushaut,leslocalescomprennentdiffrentsaspectsquitraitentchacundune
desconventionsnationalesdelalocale.Parexemple,lamaniredcrirelesnombresconstitueunde
cesaspects,toutcommelamaniredeclasserlescaractresoulamaniredcrirelesheuresetles
dates.
ChacundecesaspectsconstituecequelabibliothquestandardC++appelleunefacette.Lesfacettes
sontgrespardesclassesC++,dontlesmthodespermettentdobtenirlesinformationsspcifiques
auxdonnesquellesmanipulent.Certainesfacettesfournissentgalementdesfonctionspermettant
deformateretdinterprtercesdonnesentenantcomptedesconventionsdeleurlocale.
Chaque
facetteestidentifiedemanireuniquedansleprogramme,etchaquelocalecontientunecollection
defacettesdcrivanttoussesaspects.
LabibliothquestandardC++fournitbienentenduuncertainnombredefacettesprdfinies. Ces
facettessontregroupesencatgoriesquipermettentdelesclasserenfonctiondutypedesoprations
quellespermettentderaliser.Labibliothquestandarddfinitsixcatgoriesdefacettes,auxquelles
correspondentlesvaleursdesixconstantesdelaclasselocale:

lacatgorie ctype,quiregroupetouteslesfacettespermettantdeclassifierlescaractresetdeles
convertirdunjeudecaractreenunautre;

lacatgorie collate, qui comprenduneuniquefacettepermettant decomparerleschanesde


caractresentenantcomptedescaractresdelalocalecouranteetdelamaniredelesutiliserdans
lesclassementsalphabtiques;

lacatgorie numeric, qui comprendtouteslesfacettesprenant


nombres;

lacatgorie monetary, quicomprendlesfacettespermettantdedterminerlessymbolesmon


tairesetlamaniredcrirelesmontants;

lacatgorie time, qui comprendlesfacettescapablesdeffectuerleformatageet


datesetdesheures;

lacatgorie message,quicontientuneuniquefacettepermettantdefaciliterlinternationalisation
desprogrammesentraduisantlesmessagesdestinsauxutilisateurs.

enchargeleformatagedes

lcrituredes

Bienentendu,ilestpossiblededfinirdenouvellesfacettesetdelesincluredansunelocaleexistante.
Cesfacettesneserontvidemmentpasutilisesparlesfonctionsdelabibliothquestandard,maisle
programmepeutlesrcupreretlesutiliserdelammemanirequelesfacettesstandards.
Lesmcanismesdedfinition,didentificationetdercuprationdesfacettes,sonttousprisencharge
auniveaudelaclasselocale.Ladclarationdecetteclasseestralisedelamaniresuivantedans
lentte locale :

318

Chapitre16.Leslocales
classlocale
{
public:
//Lestypesdedonnes:
//Lescatgoriesdefacettes:
typedefintcategory;
staticconstcategory
//Lesvaleursdecesconstantes
{
//sontspcifiqueschaqueimplmentation
none
=VAL0,
ctype
=VAL1,collate =VAL2,
numeric =VAL3,monetary=VAL4,
time
=VAL5,messages=VAL6,
all=collate|ctype|monetary|numeric|time |messages;
};
//Laclassedebasedesfacettes:
classfacet
{
protected:
explicitfacet(size_trefs=0);
virtual~facet();
private:
//Cesmthodessontdclaresmaisnondfinies:
facet(constfacet&);
voidoperator=(constfacet&);
};
//Laclassedidentificationdesfacettes:
classid
{
public:
id();
private:
//Cesmthodessontdclaresmaisnondfinies:
voidid(constid&);
voidoperator=(constid&);
};
//Lesconstructeurs:
locale()throw()
explicitlocale(constchar*nom);
locale(constlocale&)throw();
locale(constlocale&init,constchar*nom,categoryc);
locale(constlocale&init1,constlocale&init2,categoryc);
template <classFacet>
locale(constlocale&init,Facet*f);
template <classFacet>
locale(constlocale&init1,constlocale&init2);
//Ledestructeur:
~locale()throw();
//Oprateurdaffectation:
constlocale&operator=(constlocale&source)throw();

319

Chapitre16.Leslocales
//Lesmthodesdemanipulationdeslocales:
basic_string<char> name()const;
booloperator==(constlocale&)const;
booloperator!=(constlocale&)const;
template <classcharT,classTraits,classAllocator
>
booloperator()(
constbasic_string<charT,Traits,Allocator> &s1,
constbasic_string<charT,Traits,Allocator> &s2)const;
//Lesmthodesdeslectiondeslocales:
static
locale global(constlocale&);
staticconstlocale&classic();
};

Commevouspouvezleconstater,outrelesconstructeurs,destructeuretmthodesgnrales,laclasse
localecontientladclarationdedeuxsousclassesutilisespourladfinitiondesfacettes:laclasse
facetetlaclasseid.
Laclassefacetestlaclassedebasedetouteslesfacettes.Sonrleestessentiellementdviterque
lonpuissedupliquerunefacetteouencopierune,cequiestralisendclarantenzoneprivele
constructeurdecopieetloprateurdaffectation.Commecesmthodesnedoiventpastreutilises,
ellesnesontpasdfiniesnonplus,seuleladclarationestfournieparlabibliothquestandard.Notez
quecelanestpasdrangeantpourlutilisationdelaclassefacet,puisquecommecesmthodesne
sontpasvirtuellesetquellesneserontjamaisutilisesdanslesprogrammes, lditeurdeliensne
chercherapasleslocaliserdanslesfichiersobjetsduprogramme.Ainsi,lesinstancesdefacettes
nepeuventtrenicopies,nidupliques.Enfait,lesfacettessontdestinestreutilisesausein
deslocales,quiprennentenchargelagestiondeleurduredevie.Toutefois,silondsiregrersoi
mmeladuredeviedunefacette,ilestpossibledelesignalerlorsdelaconstructiondelafacette.
Leconstructeurdebasedelaclassefacetprendeneffetunparamtreuniquequiindiquesiladurede
viedelafacettedoittrepriseenchargeparlalocaledanslaquelleellesetrouveousielledevratre
explicitementdtruiteparleprogrammeur(auquelcasceparamtredoittrefix 1).Engnral,la
valeurpardfaut 0 convientdanslamajoritdescasetilnestpasncessairedefournirdeparamtre
auconstructeurdesfacettes.
Laclasseidquantelleestutilisepourdfinirdesidentifiantsuniquespourchaqueclassedefacette.
Cesidentifiantspermettentlabibliothquestandarddedistinguerlesfacetteslesunesdesautres,
laideduneclefuniquedont leformat nest passpcifi, maisqui est dtermineparlaclasse
idautomatiquementlorsdelapremirecrationdechaquefacette.Cetidentifiantestenparticulier
utilispourretrouverlesfacettesdanslacollectiondesfacettesgresparlaclasselocale.
Pourquecemcanismedenregistrementfonctionne,ilfautquechaqueclassedefacettedfinisseune
donnemembrestatique id enzonepublique,dontletypeestlasousclasseiddelaclasselocale.
Cettedonnemembretantstatique, elleappartientlaclasseetnonchaqueinstance, etpermet
doncbiendidentifierchaqueclassedefacette. Lorsduchargement duprogramme, lesvariables
statiquessontinitialises0,cequifaitquelesfacettesdisposenttoutesdunidentifiantnul.Ceci
permetauxmthodesdelabibliothquestandarddedterminersiunidentifiantadjtattribula
classedunefacetteounonlorsquelleestutilisepourlapremirefois.Sicestlecas,cetidentifiant
estutilistelquelpourrfrencercetteclasse,sinon,ilestgnrautomatiquementetstockdansla
donnemembre id delaclasse.
Ainsi, pour dfinir unefacette, il suffit simplement dcrireuneclassedrivant delaclasselo
cale::facetetcontenantunedonnemembrestatiqueetpubliqueid detypelocale::id.Dslors,cette
facetteseverraattribuerautomatiquementunidentifiantunique,quipermettradutiliserlesfonctions
derecherchedefacettesdansleslocales.Cesfonctionsutilisentbienentenduladonnemembre id

320

Chapitre16.Leslocales
dutypedelafacetterechercheretsenservententantquindexdanslacollectiondesfacettesdela
localeutiliser.LamanirederalisercesoprationsnestpasdcriteparlanormeduC++,maisle
principeestl.
Lesfonctionsderecherchedesfacettessontgalementdclaresdanslentte locale.Cesontdes
fonctions template paramtresparletypedesfacettes,quiprennentenparamtrelalocaledans
laquellelafacettedoittrerecherche:
template <classFacet>
constFacet&use_facet(constlocale&);
template <classFacet>
bool
has_facet(constlocale&);

Lafonction use_facet permetdercuprerlinstancedunefacettedanslalocalepasseenpara


mtre. Commelasignaturedecettefonction template nepermetpasdedterminerletypedela
facette,etdonclinstanceutiliserpourlappel,ilestncessairedespcifierexplicitementcetype
entrecrochetsaprslenomdelafonction.Parexemple,pourrcuprerlafacettenum_put<char> de
lalocaleclassiquedelabibliothqueC,onferalappelsuivant:
use_facet<num_put<char>> (locale::classic());

Lesfacettesfourniesparlabibliothquestandardsontgnralementdisponiblesetpeuventtreuti
lisesavecleslocales.Lesmthodesspcifiqueschacunedecesfacettespeuventdonctreappe
use_facet. Enrevanche, lesfacettes
lessurlarfrencedelafacetteretourneparlafonction
dfiniesparlutilisateurpeuventnepastreprsentesdanslalocalefournieenparamtrelafonc
tion use_facet.Danscecas,cettefonctionlanceuneexceptiondetypebad_cast.Commeilpeut
treutileencertainescirconstancesdedterminerdynamiquementsiunelocalecontientounonune
facette, labibliothquestandardmet dispositionlafonctionglobale has_facet. Cettefonction
sutilisedelammemanirequelafonction use_facet, maisaulieuderenvoyerlafacettede
mande, elleretourneunboolenindiquantsilalocalefournieenparamtrecontientounoncette
facette.
Lesprogrammespeuventcrerplusieurslocalesafindeprendreencompteplusieursjeuxdepara
mtresinternationauxsilsledsirent,maisilsdoiventdanscecasmanipulerceslocaleseuxmmes
danstouteslesoprationssusceptiblesdutiliserlanotiondelocale.Parexemple,ilsdoiventspcifier
imbue desflux
lalocaleutiliseravantchaqueoprationdentre/sortieenappelantlamthode
utiliss.Commecelanestpastrspratique,labibliothquestandarddfinitunelocaleglobale,qui
estlalocaleutilisepardfautlorsquunprogrammenedsirepasspcifierexplicitementlalocale
utiliser.Cettelocalepeuttrercupretoutmomentencrantunsimpleobjetdetypelocale,en
utilisantleconstructeurpardfautdelaclasselocale.Ceconstructeurinitialiseeneffetlalocaleen
coursdeconstructionavectouslesparamtresdelalocaleglobale.Ainsi,pourrcuprerlafacette
num_put<char> delalocaleglobale,onferalappelsuivant:
use_facet<num_put<char>> (locale());

Vousremarquerezquelalocalefournieenparamtrelafonction use_facet nestplus,contraire


mentlexempleprcdent,lalocalerenvoyeparlamthodestatique classic delaclasselocale,
maisunecopiedelalocaleglobale.
Il est possibledeconstruireunelocalespcifiqueexplicitement avecleconstructeurdelaclasse
localequiprendlenomdelalocaleutiliserenparamtre.Cenompeuttrelundesnomsstandards

321

Chapitre16.Leslocales
"C", "",outouteautrevaleurdontlasignificationnestpasnormalise.Lenomdelocalevide(

"")

permetdeconstruireunelocaledontlesparamtressontinitialissenfonctiondelenvironnement
dexcutionduprogramme. Cest donclavaleurquelonutiliseraengnral, carcelapermet de
paramtrerlecomportementdesprogrammesfacilement,sansavoirlesmodifieretlesrecompiler.
Note:Lamanirededfinirlalocaledanslenvironnement dexcutiondesprogrammesest
spcifiquechaquesystmedexploitationet nest normalisni parlanormeC++, ni parla
normeC.LanormePOSIXprcisecependantquecelapeuttreralisparlintermdiairede
variablesdenvironnement.Parexemple,silavariabledenvironnementLANGnestpasdfinie,la
localeutiliseseralalocaledelabibliothqueC.Enrevanche,sicettevariabledenvironnement
contientlavaleur "fr_FR",lalocaleutiliseseracelledesfrancophonesdeFrance.Lesformats
desnombres,desdates,etc.utilissserontdoncceuxquisontenvigueurenFrance.

Lesautresconstructeursdelaclasselocalepermettentdecrerdenouvelleslocalesenrecopiantles
facettesdunelocaleexistante,ventuellementenajoutantdenouvellesfacettesnonstandardsouen
redfinissantcertainesfacettesdelalocalemodle. Bienentendu, leconstructeurdecopierecopie
touteslesfacettesdelalocalesourcedanslalocaleencoursdeconstruction.
Lesdeuxconstruc
teurssuivantspermettentderecopiertouteslesfacettesdunelocale,sauflesfacettesidentifiespar
lacatgoriespcifieentroisimeparamtre. Pourcettecatgorie, lesfacettesutilisessontcelles
delalocalespcifieendeuximeparamtre.
Il est possibleici didentifiercettedeuximelocale
soitparsonnom,soitdirectementparlintermdiairedunerfrence.Enfin,lesdeuxconstructeurs
template permettentdecrerunelocaledonttouteslesfacettessontinitialisespartirdunelo
calefournieenparamtre, sauflafacettedontletypeestutilisentantqueparamtre template.
Pourcettefacette,lavaleurutiliserpeuttrespcifiedirectementendeuximeparamtreouex
traiteduneautrelocale,elleaussispcifieendeuximeparamtre.Nousverronsplusendtaildans
laSection16.3lamaniredeprocderpourinsrerunenouvellefacetteouremplacerunefacette
existante.
Enfin,laclasselocaledisposededeuxmthodesstatiquespermettantdemanipulerleslocalesdupro
gramme.Lamthode classic quelonautilisedanslundesexemplesprcdentspermetdobtenir
lalocalereprsentantlesoptionsdelabibliothqueCstandard.Cettelocaleestlalocaleutilisepar
dfautparlesprogrammesquinedfinissentpasleslocalesutilises.Lamthode global quant
ellepermetdespcifierlalocaleglobaleduprogramme.Cettemthodeprendenparamtreunobjet
detypelocalepartirduquellalocaleglobaleestinitialise.Ilestdonccourantdefaireunappel
cettemthodedsledbutdesprogrammesC++.
Exemple161.ProgrammeC++prenantencomptelalocaledelenvironnement
#include <ctime>
#include <iostream>
#include <locale>
usingnamespacestd;
intmain(void)
{
//Utiliselalocaledfiniedanslenvironnement
//dexcutionduprogramme:
locale::global(locale(""));
//Afficheladatecourante:
time_tdate;
time(&date);
structtm*TL=localtime(&date);

322

Chapitre16.Leslocales
use_facet<time_put<char>> (locale()).put(
cout,cout,,TL,c);
cout << endl;
//Afficheladateaveclafonctionstrftime
//delabibliothqueC:
chars[64];
strftime(s,64,"%c",TL);
cout << s << endl;
return0;
}

Lamthode global delaclasseglobalappelleautomatiquementlamthode setlocale silalocale


fournieenparamtreaunnom.CelasignifiequeleslocalesdelabibliothquestandardC++etcelles
delabibliothquestandardCsontcompatiblesetutilisentlesmmesconventionsdenommage.En
particulier,lesprogrammesquiveulentutiliserlalocaledfiniedansleurenvironnementdexcution
peuventutiliserlalocaleanonyme "".Cestcequefaitleprogrammedelexempleprcdent, qui
afficheladateauformatdelalocaledfinieparlutilisateurenpassantparlesmcanismesduC++
(vialafacettetime_put,quiseradcriteendtaildanslaSection16.2.6)etparlafonctionstrftime
delabibliothqueC.
Note:Lesfonctions time, localtime et strftime sontdesfonctionsdelabibliothqueCstan
dard.Ellespermettentrespectivementdobtenirunevaleurdetypetime_treprsentantladate
courante,delaconvertirenunestructurecontenantlesdiffrentescomposantesdeladateen
tempslocal,etdeformatercettedateselonlesconventionsdelalocalecourante.Cesfonctions
neserontpasdcritesplusendtail ici.Vouspouvezconsulterlabibliographiesi vousdsirez
obtenirplusdedtailssurlabibliothqueCetlesfonctionsquellecontient.

16.2.Lesfacettesstandards
Cettesectionprsentelensembledesfacettesstandardsdfiniesparlabibliothquestandard.
La
premirepartiedcritlarchitecturegnralelaquellelesfacettesstandardsseconforment,
etles
partiessuivantesdonnent unedescriptiondesprincipalesfonctionnalitsfourniesparchacunedes
catgoriesdefacettes.

16.2.1.Gnralits
Lesfacettesfourniesparlabibliothquestandardsontdesclasses template paramtresparletype
descaractressurlesquelsellestravaillent.Pourquelquesunesdecesfacettes,labibliothquestan
darddfinitunespcialisationpourlestypescharouwchar_t,spcialisationdontlebutestdoptimiser
lestraitementsdesfacettespourlesfluxdentre/sortiestandardssurcestypes.
Certainesdecesfacettesnesontutilisesquepourfournirdesinformationsauxautrespartiesdela
bibliothquestandardC++. Dautres, enrevanche, permettent deraliserlesoprationsdeforma
tageetdanalysesyntaxiquesurlesquelleslesfluxdentre/sortiesappuientpourimplmenterles
oprateurs operator<< et operator>>.Cesfacettesdisposentalorsdemthodes put et get qui
permettentdeffectuercesdeuxtypesdopration.
Lestraitementseffectusparlesfacettesdoiventprendreencomptelesparamtresdeleurlocaleain
siquelesoptionsdeformatagestockesdanslesfluxsurlesquelleslesentres/sortiesdoiventtre
effectues.Pourcela,lesfacettesdoiventdisposerdunmoyendercuprerlalocaledontellesfont

323

Chapitre16.Leslocales
partieoudontellesdoiventutiliserlesparamtres.Gnralement,lesfacettesquiralisentlesopra
tionsdentre/sortiepourlecomptedesfluxutilisentlamthodegetloc decesdernierspourobtenir
lalocaledontellesdoiventutiliserlesparamtres.Lesautresfacettesnepeuventpasprocderdela
mmemanire,carellesnedisposentpasforcmentdunobjetfluxpourdterminerlalocalecou
rante.Afindersoudreceproblme,labibliothquestandarddfinitdesclassesdefacettesdrives
etdontleconstructeurprendenparamtrelenomdelalocalelaquellecesfacettesappartiennent.
Cesclassessontdoncinitialises,dsleurconstruction,aveclenomdelalocaledanslaquelleelles
setrouvent,cequileurpermetventuellementdeffectuerdestraitementsdpendantsdecettelocale.
Lesnomsdecesclassesdefacettesdrivessontlesmmesqueceuxdeleursclassesdebase,

_byname .Parexemple,lafacettectype,qui,comme
ceciprsquilssontsuffixsparlachane
onleverraplusloin,permetdeclasserlescaractresselonleurnature,disposeduneclassedrive
ctype_bynamedontleconstructeurprendenparamtrelenomdelalocaledontlafacettefaitpartie.
Note:Lesimplmentationsdelabibliothquestandardfourniesaveclesenvironnementsde
dveloppementC++nesontpastenuesdefournircesfacettespourchaquelocaleexistantedans
lemonde.Enralit,quasimentaucunenvironnementnelefaitlheureactuelle.Enrevanche,
touteslesfacettesstandardsdoiventaumoinstrefourniesetfonctionnercorrectementavecles
locales "C" et "".

Lesfacettessont critesdetellemanirequellespeuvent facilement treremplacespardesfa


cettesplusspcifiques.Ainsi,leursmthodespubliquesappellenttoutesdesmthodesvirtuelles,qui
peuventparfaitementtreredfiniespardesclassesdrivesdsirantremplacerlundestraitements
effectusparlabibliothquestandard.
Gnralement,lesnomsdesmthodesvirtuellessontlesmmesqueceuxdesmthodespubliquesqui
lesutilisent,prcdsduprfixe do_ .Parexemple,siunefacettefournitunemthodepublique
nomme put,lamthodevirtuelleappeleparcellecisenommera do_put.Lamanirederedfinir
lesmthodesdunefacetteexistanteetderemplacercettefacetteparunedesesclassesdrivesdans
unelocaleseradcriteendtaildanslaSection16.3.2.

16.2.2.Lesfacettesdemanipulationdescaractres
Labibliothquestandarddfinitdeuxfacettespermettantdemanipulerlescaractres.
Lapremire
facette,lafacettectype,fournitlesfonctionspermettantdeclasserlescaractresendiffrentescat
gories.Cescatgoriescomprennentleslettres,leschiffres,lescaractresimprimables,lescaractres
graphiques,etc.Ladeuximefacettepermetquantelledeffectuerlesconversionsentrelesdiff
rentstypesexistantsdencodagedecaractres.Ilsagitdelafacettecode_cvt.

16.2.2.1.Lafacettectype
Lafacettectypedriveduneclassedebasedanslaquellesontdfinieslesdiffrentescatgoriesde
caractres.Cetteclasseestdclarecommesuitdanslentte locale :
classctype_base
{
public:
enummask
{
space=SPACE_VALUE,print=PRINT_VALUE,
cntrl=CNTRL_VALUE,alpha=ALPHA_VALUE,
digit=DIGIT_VALUE,xdigit=XDIGIT_VALUE,

324

Chapitre16.Leslocales
upper=UPPER_VALUE,lower=LOWER_VALUE,
punct=PUNCT_VALUE,
alnum=alpha|digit,graph=alnum|punct
};
};

Les valeurs numriques utilises par cettenumrationsont dfinies detellemanirequeles


constantes detypemaskconstituent unchampdebits. Ainsi, il est possiblededfinir des
combinaisonsentrecesvaleurs, certainscaractrespouvant appartenir plusieurscatgoriesen
mmetemps. Deuxcombinaisonsstandardssont dailleursdfinies, alnum, qui caractriseles
caractresalphanumriques, et graph, qui reprsentetouslescaractresalphanumriqueset de
ponctuation.Lesautresconstantespermettentdecaractriserlescaractresselonleurnatureetleur
significationestengnralclaire.Laseuleconstantequidontlinterprtationnestpasimmdiateest
laconstante xdigit,quiidentifietouslescaractrespouvantservirdechiffredanslanotationdes
nombreshexadcimaux.Celacomprendleschiffresnormauxetleslettres A F.
Laclasse template ctypequantelleestdclarecommesuitdanslentte locale :
template <classcharT>
classctype:publiclocale::facet,publicctype_base
{
public:
//Lestypesdedonnes:
typedefcharTchar_type;
//Leconstructeur:
explicitctype(size_trefs=0);
//Lesmthodedeclassification:
bool
is(maskm,charTc)const;
constcharT*is(constcharT*premier,constcharT*dernier,
mask*vecteur)const;
constcharT*scan_is(maskm,
constcharT*premier,constcharT*dernier)const;
constcharT*scan_not(maskm,
constcharT*premier,constcharT*dernier)const;
charT
toupper(charTc)const;
constcharT*toupper(constcharT*premier,constcharT*dernier)const;
charT
tolower(charTc)const;
constcharT*tolower(constcharT*premier,constcharT*dernier)const;
charT
widen(charc)const;
constcharT*widen(constchar*premier,constchar*dernier,
charT*destination)const;
char
narrow(charTc,chardefaut)const;
constchar *narrow(constcharT*premier,constcharT*dernier,
chardefaut,char*destination)const;
//Lidentificateurdelafacette:
staticlocale::idid;
};

Note:Commepourtouteslesfacettesstandards,lesmthodespubliquesdlguentleurtravail
desmthodesvirtuellesdclaresenzoneprotgedontlenomestceluidelamthodepublique
prfixparlachanedecaractresdo_ .Cesmthodespeuventtreredfiniesparlesclasses
drivesdelafacettectypeetfontdoncpartiedelinterfacedesfacettesstandards.Cependant,

325

Chapitre16.Leslocales
ellesnesontpasreprsentesdansladclarationdonnecidessusparsoucidesimplicit.Leur
smantiqueestexactementlammequecelledesmthodespubliquescorrespondantes.Nous
verronsdanslaSection16.3.2lamaniredeprocderpourredfinircertainesdesmthodesdes
facettesstandards.

Lesmthodes scan_is et scan_not permettentderechercheruncaractreselonuncritreparti


culierdansuntableaudecaractres.Lamthode scan_is recherchelepremiercaractrequiestdu
typeindiquparsonparamtre m,etlamthode scan_not lepremiercaractrequinestpasdece
type.Cesdeuxmthodesprennentenparamtreunpointeursurlepremiercaractredutableaudans
lequellarecherchedoitseffectueretlepointeursuivantlemplacementduderniercaractredece
tableau.Ellesrenvoienttouteslesdeuxunpointeurrfrenantlecaractretrouv,oulepointeurde
finsiaucuncaractrenevrifielecritrespcifi.
Lesautresmthodesdelafacettectypesont
fourniessousdeuxversions. Lapremirepermet
deffectuer uneoprationsur uncaractreuniqueet
ladeuximepermet dereproduirecette
oprationsurunesquencedecaractresconscutifs.Danscederniercas,lescaractressurlesquels
loprationpeuttreeffectuesontspcifislaidededeuxpointeurs,lunsurlepremiercaractre
etlautresurlecaractresuivantlederniercaractredelasquence,commeilestdusagedelefaire
danstouslesalgorithmesdelabibliothquestandard.
Lesdeuxmthodes is permettent doncrespectivement dedterminersi uncaractreest dutype
indiquparleparamtre m ounon,oudobtenirlasuitedesdescriptionsdechaquecaractredansle
tableaudevaleurdetypemaskpointparleparamtre vecteur.Demme,lesmthodes toupper
et tolower permettentrespectivementdeconvertiruncaractreuniqueoutouslescaractresdun
tableauenmajusculeouenminuscule.Lamthode widen permetdetranstyperuncaractreoutous
lescaractresduntableaudetypecharencaractresdutypeparlequellaclassectypeestparamtre.
Enfin,lesmthodesnarrow permettentderaliserloprationinverse,cequipeutprovoqueruneperte
dedonnespuisqueletypecharestlepluspetitdestypesdecaractresquipuisseexister.Ilestdonc
possiblequeletranstypagenepuissesefaire,danscecas,lesmthodes narrow utilisentlavaleurpar
dfautspcifieparleparamtre defaut.
Exemple162.Conversiondunewstringenstring
#include <iostream>
#include <string>
#include <locale>
usingnamespacestd;
intmain(void)
{
//Fixelalocaleglobaleauxprfrencesdelutilisateur:
locale::global(locale(""));
//Litunechanedecaractreslarges:
wstringS;
wcin >> S;
//Rcuprelafacettectype
<wchar_t> delalocalecourante:
constctype<wchar_t> &f=
use_facet<ctype<wchar_t>> (locale());
//Construituntamponpourrecevoirlersultatdelaconversion:
size_tl=S.length()+1;
char*tampon=newchar[l];
//Effectuelaconversion:
f.narrow(S.c_str(),S.c_str()+l,E,tampon);

326

Chapitre16.Leslocales
//Affichelersultat:
cout << tampon << endl;
delete[]tampon;
return0;
}
Note:Lesconversionseffectuesparlesmthodes narrow et widen netravaillentquavecles
reprsentationsdecaractresclassiquesdulangageC++.Celasignifiequelescaractressont
tousreprsentsparuneuniquevaleurdetypecharouwchar_t(cesmthodesnutilisentdonc
pasdereprsentationdescaractresbasessurdessquencesdecaractresdelongueurs
variables).Lamthode narrow delexempleprcdentcritdoncautantdecaractresdansle
tampondestinationquilyenadanslachaneconvertir.

Vousconstaterezquelutilisationdelamthode is pourdterminerlanaturedescaractrespeut
trerelativementfastidieuse,carilfautrcuprerlafacettectype,dterminerlavaleurdumasque
utiliser,puisappelerlamthode.Labibliothquestandarddfinitdoncuncertainnombredefonctions
globalesutilitairesdanslentte locale :
template
template
template
template
template
template
template
template
template
template
template
template
template

<classcharT>
<classcharT>
<classcharT>
<classcharT>
<classcharT>
<classcharT>
<classcharT>
<classcharT>
<classcharT>
<classcharT>
<classcharT>
<classcharT>
<classcharT>

boolisspace(charTc,constlocale&l)const;
boolisprint(charTc,constlocale&l)const;
booliscntrl(charTc,constlocale&l)const;
boolisupper(charTc,constlocale&l)const;
boolislower(charTc,constlocale&l)const;
boolisalpha(charTc,constlocale&l)const;
boolisdigit(charTc,constlocale&l)const;
boolispunct(charTc,constlocale&l)const;
boolisxdigit(charTc,constlocale&l)const;
boolisalnum(charTc,constlocale&l)const;
boolisgraph(charTc,constlocale&l)const;
charTtoupper(charTc,constlocale&l)const;
charTtolower(charTc,constlocale&l)const;

Lutilisationdecesfonctionsnedoitpasposerdeproblmeparticulier.Ellesprennenttoutesenpre
mierparamtrelecaractrecaractriseretendeuximeparamtrelalocaledontlafacettectype
doittreutilisepourralisercettecaractrisation.Chaquefonctionpermetdetesterlecaractrepour
lappartenancelunedescatgoriesdecaractresdfiniesdanslaclassedebasectype_base.Notez
cependantquesiungrandnombredecaractresdoiventtrecaractrisspourunemmelocale,ilest
plusperformantdobtenirlafacettectypedecettelocaleunebonnefoispourtoutesetdeffectuerles
appelslamthode is enconsquence.
Laclassectypetantuneclasse template,ellepeuttreutilisepournimportequeltypedecaractre
apriori. Toutefois, il est vident quecetteclassepeut treoptimisepourlestypesdecaractre
simples,ettoutparticulirementpourletypechar,parcequilnepeutpasprendreplusde256valeurs
diffrentes. Labibliothquestandarddfinit doncunespcialisationtotaledelaclasse template
ctypepourletypechar.Limplmentationdecettespcialisationsebasesuruntableaudevaleursde
typemaskindexeparlesvaleursquepeuventprendrelesvariablesdetypechar.Cetableaupermet
doncdedterminerrapidementlescaractristiquesdechaquecaractreexistant.Leconstructeurde
cettespcialisationdiffrelgrement duconstructeurdesaclasse template caril peut prendre
enparamtreunpointeursurcetableaudevaleursetunboolenindiquantsicetableaudoittre
dtruit automatiquement parlafacettelorsquelleest ellemmedtruiteounon. Ceconstructeur
prendgalemententroisimeparamtreunevaleurdetypeentierindiquant,commepourtoutesles
facettesstandards,silalocaledoitprendreenchargelagestiondeladuredeviedelafacetteounon.

327

Chapitre16.Leslocales
Lesautresmthodesdecettespcialisationsontidentiquesauxmthodesdelaclasse template de
baseetneserontdoncpasdcritesici.

16.2.2.2.Lafacettecodecvt
Lafacettecodecvtpermetderaliserlesoprationsdeconversiondunmodedereprsentationdes
caractresunautre.Engnral,eninformatique,lescaractressontcodspardesnombres.Letype
decesnombres,ainsiquelamaniredelesutiliser,peutvariergrandementdunereprsentationune
autre,etlesconversionspeuventnepassefairesimplement.Parexemple,certainesreprsentations
codentchaquecaractreavecunevaleuruniquedutypedecaractreutilis,maisdautrescodentles
caractressurdessquencesdelongueurvariable.Onnepeutdanscecasbienentendupasconver
tirdirectementunereprsentationenuneautre,carlinterprtationquelonpeutfairedesnombres
reprsentantlescaractresdpendducontextedterminparlesnombresdjlus.Lesoprationsde
conversionnesontdoncpastoujoursdirectes.
Deplus,danscertainsencodagestaillevariable,linterprtationdescaractrespeutdpendredes
caractresdjconvertis.Lafacettecodecvtmaintientdoncuntatpendantlesconversionsquelle
effectue, tat qui lui permet dereprendrelaconversiondunesquencedecaractresdanslecas
deconversionsralisesenplusieurspasses. Bienentendu, touslesencodagesnencessitent pas
forcmentlemaintiendunteltat.Cependant,certainslexigentetilfautdonctoujoursleprendre
encomptedanslesoprationsdeconversionsilonsouhaitequeleprogrammesoitportable.Pour
lessquencesdecaractresencodagevariableutilisantletypedecaractredebasechar,letypede
lavariabledtatpermettantdestockerltatcourantduconvertisseurestletypembstate_t.Dautres
typespeuventtreutilisspourlessquencesbasessurdestypesdecaractresdiffrentsdutype
char,maisengnral,touslesencodagestaillevariablesebasentsurcetype.Quoiquilensoit,
laclassecodecvtdfinituntypededonnecapabledestockerltatduneconversionpartielle.Ce
typeestletypestate_type,quipourradonctoujourstrercuprdanslaclassecodecvt.Lavariable
dtatduconvertisseurdevratresystmatiquementfournieauxmthodesdeconversiondelafacette
codecvt et devrabienentendutreinitialisesavaleurpardfaut audbut dechaquenouvelle
conversion.
Note:Lafacettecodecvt permet deraliserlesconversionsdunereprsentationdescarac
tresuneautre, maisnapaspour but dechanger lencodagedescaractres, cestdire
lassociationqui est faiteentrelessquencesdenombreset lescaractres. Celasignifieque
lafacettecodecvtpermetparexempledeconvertirdeschanesdecaractreslargeswchar_ten
squencesdelongueursvariablesdecaractresdetypechar,maisellenepermetpasdepasser
dunepagedecodesuneautre.

Lafacettecodecvtdriveduneclassedebasenommecodecvt_base. Cetteclassedfinitlesdif
frentsrsultatsquepeuventavoirlesoprationsdeconversion. Elleestdclarecommesuitdans
lentte locale :
classcodecvt_base
{
public:
enumresult
{
ok,partial,error,noconv
};
};

328

Chapitre16.Leslocales
Commevouspouvezleconstater,uneconversionpeutseralisercompltement(codedersultatok),
partiellementparmanquedeplacedanslasquencedestinationouparmanquededonnesenentres
(code partial),oupasdutout,soitenraisonduneerreurdeconversion(codederreurerror),soit
parcequaucuneconversionnestncessaire(codedersultat noconv).
Laclasse template codecvtellemmeestdfiniecommesuitdanslentte locale :
template <classinternT,classexternT,classstateT
>
classcodecvt:publiclocale::facet,publiccodecvt_base
{
public:
//Lestypesdedonnes:
typedefinternTintern_type;
typedefexternTextern_type;
typedefstateT state_type;
//Leconstructeur:
explicitcodecvt(size_trefs=0);
//Lesfonctionsdeconversion:
resultout(stateT&etat,constinternT*premier,
constinternT*dernier,constinternT*&suiv_source,
externT*dernier,externT*limite,externT*&suiv_dest)const;
resultin(stateT&etat,constexternT*premier,
constexternT*dernier,constexternT*&suiv_source,
internT*dernier,internT*limite,internT*&suiv_dest)const;
resultunshift(stateT&etat,
externT*dernier,externT*limite,externT*&suiv_dest)const;
intlength(conststateT&etat,
constexternT*premier,constexternT*dernier,size_tmax)const;
intmax_length()constthrow();
intencoding()constthrow();
boolalways_noconv()constthrow();
//Lidentificateurdelafacette:
staticlocale::idid;
};

Note:Lesmthodesvirtuellesdimplmentationdesmthodespubliquesnontpastcrites
dansladclarationprcdenteparsoucidesimplification.Ellesexistentmalgrtout,etpeuvent
treredfiniesparlesclassesdrivesafindepersonnaliserlecomportementdelafacette.

Cetteclasse template estparamtreparletypedecaractreinternelaclassecodecvt,


parun
deuximetypedecaractrequiseraparlasuitednommtypeexterne,etparletypedesvariables
destinesrecevoirltatcourantduneconversion.Lesimplmentationsdelabibliothquestandard
doiventobligatoirementinstanciercetteclasse template pourlestypescharetwchar_t.Letypede
gestiondeltatdesconversionsutilisestalorsletypeprdfinimbstate_t,quipermetdeconser
verltatdesconversionsentreletypenatifwchar_tetlessquencesdecaractressimplestaille
variable. Ainsi, vouspourreztoujoursutiliserlesinstancescodecvt <wchar_t, char, mbstate_t> et
codecvt<char,char,mbstate_t> delafacettecodecvtdansvosprogrammes.Sivousdsirezraliser
desconversionspourdautrestypesdecaractres,vousdevrezfournirvousmmedesspcialisations
delafacettecodecvt.

329

Chapitre16.Leslocales
Lesmthodes in et out permettentrespectivement,commeleurssignatureslindiquent,deraliser
lesconversionsentrelestypesinterneetexterneetviceversa.Ellesprennenttoutesdeuxseptpara
mtres.Lepremierparamtreestunerfrencesurlavariabledtatquidevratrefourniechaque
appellorsdeconversionssuccessivesdunmmefluxdedonnes.Cettevariableestdestinere
cevoirltatcourantdelaconversionetpermettraauxappelssuivantsdeconvertircorrectementles
caractressuivantsdufluxdentre.Lesdeuxparamtressuivantspermettentdespcifierlasquence
decaractresconvertir.Ilsdoiventcontenirlepointeursurledbutdelasquenceetlepointeursur
lecaractresuivantlederniercaractredelasquence.Lequatrimeparamtreestunparamtrede
retour,lafonctionluiaffecteralavaleurdupointeurolaconversionsestarrte.Uneconversion
peutsarrtercauseduneerreuroutoutsimplementparcequeletampondestinationnecontient
pasassezdeplacepouraccueilliruncaractredeplus.
Cepointeurpourratreutilisdansunap
pelultrieurcommepointeurdedpartaveclavaleurdelavariabledtatlissuedelaconversion
poureffectuerlasuitedecetteconversion.Enfin,lestroisderniersparamtresspcifientletampon
destinationdanslequellasquenceconvertiedoittrecrite.Ilspermettentdindiquerlepointeurde
dbutdecetampon, lepointeursuivantledernieremplacementutilisable, etunpointeurderetour
quiindiqueraladernirepositioncriteparloprationdeconversion.Cesdeuxmthodesrenvoient
unedesconstantesdelnumrationresultdfiniedanslaclassedebasecodecvt_basepourindiquer
commentlaconversionsesteffectue. Siaucuneconversionnestncessaire, lespointeurssurles
caractressuivantssontinitialisslavaleurdespointeursdedbutdesquenceetaucunecriture
nalieudansletampondestination.
Exemple163.Conversiondunechanedecaractreslargesenchaneencodagevariable
#include <iostream>
#include <string>
#include <locale>
usingnamespacestd;
intmain(void)
{
//Fixelalocaleglobale:
locale::global(locale(""));
//Lituneligne:
wstringS;
getline(wcin,S);
//Rcuprelafacettedeconversionverswchar_t:
constcodecvt<wchar_t,char,mbstate_t
> &f=
use_facet<codecvt<wchar_t,char,mbstate_t
>> (locale());
//Effectuelaconversion:
constwchar_t*premier=S.c_str();
constwchar_t*dernier=premier+S.length();
constwchar_t*suivant=premier;
strings;
chartampon[10];
char*fincvt=tampon;
codecvt_base::resultr;
mbstate_tetat=mbstate_t();
while(premier!=dernier)
{
//Convertitunmorceaudelachane:
r=f.out(etat,premier,dernier,suivant,
tampon,tampon+10,fincvt);
//Vrifieleserreurspossibles:
if(r==codecvt_base::ok||r==codecvt_base::partial)

330

Chapitre16.Leslocales
cout << "." << flush;
elseif(r==codecvt_base::noconv)
{
cout << "conversionnonncessaire"<< endl;
break;
}
elseif(r==codecvt_base::error)
{
cout << "erreur" << endl;
cout << suivantpremier << endl;
cout << fincvttampon << endl;
break;
}
//Rcuprelersultatetprparelaconversionsuivante:
s.append(tampon,fincvttampon);
premier=suivant;
}
cout << endl;
//Affichelersultat:
cout << s << endl;
return0;
}
Note:Silondsireeffectuerunesimpleconversiondunechanedecaractresdetypewchar_t
enchanedecaractresCclassique, onchercheraplutt utiliserlamthode narrow dela
facettectypeprsentedanslasectionprcdente.Eneffet,lafacettecodecvtutilise,apriori,
unesquencedecaractresavecunencodagetaillevariable,cequi necorrespondpasla
reprsentationdeschanesdecaractresCclassiques,pourlesquelleschaquevaleurdetype
charreprsenteuncaractre.

Il est possibledecomplterunesquencedecaractresencodagevariabledetellesortequela
variabledtatduconvertisseursoitrinitialise. Celapermetdeterminerunechanedecaractres
partiellement convertie, cequi enpratiquerevient complterlasquencedecaractresavecles
donnesquireprsenterontlecaractrenulterminal. Cetteoprationpeuttreraliselaidede
lamthode unshift delafacettecodecvt.Cettemthodeprendenparamtreunerfrencesurla
variabledtatduconvertisseur,ainsiquelespointeursdedbutetdefindutampondanslequelles
valeursajoutersontcrites.Ledernierparamtredelamthode unshift estunerfrencesurun
pointeurquirecevraladressesuivantcelleladernirevaleurcriteparlamthodesiloprationse
droulecorrectement.
Ilvadesoiqueladterminationdelalongueurdunechanedecaractresdontlescaractresont
unereprsentationtaillevariablenestpassimple.Lafacettecodecvtcomportedoncunemthode
length permettantdecalculer,ennombredecaractresdetypeintern_type,lalongueurdunes
quencedecaractresdetypeextern_type. Cettemthodeprendenparamtrelavariabledtatdu
convertisseurainsiquelespointeursspcifiantlasquencedecaractresdontlalongueurdoittre
calcule.Ledernierparamtreestlavaleurmaximalequelafonctionpeutretourner.Ellepermetde
limiterladterminationdelalongueurdelasquencesourceunebornemaximale,parexemplela
tailleduntampondestination. Lavaleurretourneestbienentendulalongueurdecettesquence
ou, autrementdit, lenombredevaleursdetypeintern_typencessairespourstockerlersultatde
laconversionquelamthode in feraitaveclesmmesparamtres. Dautrepart, ilestpossiblede
dterminerlenombremaximaldevaleursdetypeintern_typencessairespourreprsenterununique
caractrereprsentparunesquencedecaractresdetypeextern_type.Pourcela,ilsuffitdappeler
lamthode max_length delafacettecodecvt.

331

Chapitre16.Leslocales
Exemple164.Dterminationdelalongueurdunechanedecaractresencodagevariable
#include
#include
#include
#include

<iostream>
<string>
<locale>
<limits>

usingnamespacestd;
intmain(void)
{
//Fixelalocaleglobale:
locale::global(locale(""));
//Lituneligne:
strings;
getline(cin,s);
//Rcuprelafacettedeconversionverswchar_t:
constcodecvt<wchar_t,char,mbstate_t
> &f=
use_facet<codecvt<wchar_t,char,mbstate_t
>> (locale());
//Affichelalongueurdelachanedentre:
intl1=s.length();
//Calculelalongueurdelaligneenwchar_t:
mbstate_tetat=mbstate_t();
intl2=f.length(etat,s.c_str(),s.c_str()+l1,
numeric_limits<size_t>::max());
//Affichelesdeuxlongueurs:
cout << l1 << endl;
cout << l2 << endl;
return0;
}

Commeonladjindiqucidessus, touteslesreprsentationsdescaractresnesontpastaille
variableettouteslesreprsentationsnencessitentpasforcmentlutilisationdunevariabledtatde
typestate_type.Vouspouvezdterminerdynamiquementsilemodedereprsentationdescaractres
encoding.
dutypeintern_typeutiliseunencodagetaillevariableounonlaidedelamthode
Cettemthoderenvoie 1 silareprsentationdescaractresdetypeextern_typedpenddeltatdu
convertisseur,oulenombredecaractresdetypeextern_typencessairesaucodageduncaractrede
typeintern_typesicenombreestconstant.Silavaleurrenvoyeest 0,cenombrenestpasconstant,
mais,contrairementcequisepasselorsquelavaleurrenvoyeest 1,cenombrenedpendpasde
lavaleurdelavariabledtatduconvertisseur.
Enfin,certainsmodesdereprsentationdescaractressontcompatibles,voirefranchementidentiques.
in et out renvoienttoujours
Danscecas,jamaisaucuneconversionnestralise,etlesmthodes
noconv.Cestparexemplelecasdelaspcialisationcodecvt <char,char,mbstate_t> delafacette
codecvt. Vouspouvezdterminersi unefacetteeffectueradesconversionsounonenappelant la
mthode always_noconv.Elleretourne true sijamaisaucuneconversionneseferaetfalse sinon.

16.2.3.Lesfacettesdecomparaisondechanes
Leschanesdecaractressontgnralementclassesparordrealphabtique, ou, plusprcisment,
danslordrelexicographique.Lordrelexicographiqueestlordredfiniparlasquencedessymboles
lexicauxutiliss(cestdirelessymbolesutilisspourformerlesmotsdulangage,donc,enpratique,
leslettres, lesnombres, laponctuation, etc.). Cetordreestceluiquiestdfiniparlacomparaison
successivedescaractresdesdeuxchanescomparer,
lepremiercoupledecaractresdiffrents

332

Chapitre16.Leslocales
permettantdedonnerunjugementdeclassement.Ainsi,leschaneslespluspetitesausensdelordre
lexicographiquesontleschanesquicommencentparlespremierssymbolesdulexiqueutilis.Cette
maniredeprocdersupposebienentenduquelessymbolesutilisspourformerlesmotsdulexique
sontclasssdansunordrecorrect.Parexemple,ilfautquelalettre aapparaisseavantlalettre b,
quiellemmedoitapparatreavantlalettre c,etc.
Malheureusement,celanestpassisimple,carcetordrenestgnralementpasceluiutilisparles
pagesdecodesdunepart,etilexistetoujoursdessymbolesspciauxdontlaclassificationncessite
untraitementspcialdautrepart.Parexemple,lescaractresaccentussontgnralementplacsen
findepagedecodeetapparaissentdonclafindelordrelexicographique,cequiperturbeautoma
tiquementleclassementdeschanesdecaractrescontenantdesaccents.Demme,certaineslettres
sontenralitdescompositionsdelettresetdoiventtreprisesencompteentantquetellesdansles
oprationsdeclassement.Parexemple,lalettre doittreinterprtecommeun asuividun e.
Etquedireducasparticulierdesmajusculesetdesminuscules?
Commevouspouvezleconstater,ilnestpaspossibledesebaseruniquementsurlordredescarac
tresdansleurpagedecodepoureffectuerlesoprationsdeclassementdechanesdecaractres.De
plus,ilvadesoiquelordreutilispourclasserlessymboleslexicographiquesdpenddecessym
bolesetdoncdelalocaleutilis.Labibliothquestandardfournitdoncunefacetteprenantencompte
touscesparamtres:laclasse template collate.
Leprincipedefonctionnementdelafacettecollateestdetransformerleschanesdecaractresuti
lisantlesconventionsdelalocalelaquellelafacetteappartientenunechanedecaractresind
pendantedelalocale,comprenantventuellementdescodesdecontrlespciauxpourlescaractres
spcifiquescettelocale.Leschanesdecaractresainsitransformespeuventalorstrecompares
entreellesdirectement,aveclesmthodesdecomparaisonclassiquedechanesdecaractresquiuti
lisentlordrelexicographiquedujeudecaractresdulangageC.Latransformationesteffectuede
tellemanirequecettecomparaisonproduitlemmersultatquelacomparaisontenantcomptedela
localedeschanesdecaractresnontransformes.
Lafacettecollateestdclarecommesuitdanslentte locale :
template <classcharT>
classcollate:publiclocale::facet
{
public:
//Lestypesdedonnes:
typedefcharT
char_type;
typedefbasic_string<charT> string_type;
//Leconstructeur:
explicitcollate(size_trefs=0);
//Lesmthodesdecomparaisondechanes:
string_typetransform(constcharT*debut,constcharT*fin)const;
intcompare(constcharT*deb_premier,constcharT*fin_premier,
constcharT*deb_deuxieme,constcharT*fin_deuxieme)const;
longhash(constcharT*debut,constcharT*fin)const;
//Lidentificateurdelafacette:
staticlocale::idid;
};

333

Chapitre16.Leslocales
Note:Lesmthodesvirtuellesdimplmentationdesmthodespubliquesnontpastcrites
dansladclarationprcdenteparsoucidesimplification.Ellesexistentmalgrtout,etpeuvent
treredfiniesparlesclassesdrivesafindepersonnaliserlecomportementdelafacette.

Lamthode transform estlamthodefondamentaledelafacettecollate.Cestcettemthodequi


permetdobtenirlachanedecaractrestransforme.Elleprendenparamtrelepointeursurledbut
delachanedecaractrestransformeretlepointeursurlecaractresuivantlederniercaractrede
cettechane.Elleretourneunebasic_stringcontenantlachanetransforme,surlaquellelesopra
tionsdecomparaisonclassiquespourronttreappliques.
Ilestpossibledeffectuerdirectementlacomparaisonentredeuxchanesdecaractres,sansavoir
rcuprerleschanesdecaractrestransformes.Celapeuttreralisgrcelamthode compare,
quiprendenparamtrelespointeursdedbutetdefindesdeuxchanesdecaractrescompareretqui
renvoieunentierindiquantlersultatdelacomparaison.Cetentierestngatifsilapremirechane
estinfrieureladeuxime,positifsielleestsuprieure,etnulsilesdeuxchanessontquivalentes.
Exemple165.Comparaisondechanesdecaractreslocalises
#include <iostream>
#include <string>
#include <locale>
usingnamespacestd;
intmain(void)
{
//Fixelalocaleglobale:
locale::global(locale(""));
//Litdeuxlignesenentre:
cout << "Entrezlapremireligne:"<< endl;
strings1;
getline(cin,s1);
cout << "Entrezladeuximeligne:"<< endl;
strings2;
getline(cin,s2);
//Rcuprelafacettedecomparaisondechanes:
constcollate<char> &f=
use_facet<collate<char>> (locale());
//Comparelesdeuxchanes:
intres=f.compare(
s1.c_str(),s1.c_str()+s1.length(),
s2.c_str(),s2.c_str()+s2.length());
if(res < 0)
{
cout << "\"" << s1 << "\"estavant\""
<<
s2 << "\"." << endl;
}
elseif(res > 0)
{
cout << "\"" << s1 << "\"estaprs\""
<<
s2 << "\"." << endl;
}
else
{
cout << "\"" << s1 << "\"estgale\""
<<

334

Chapitre16.Leslocales

s2 << "\"." << endl;


return0;

}
Note:Lamthode compare est trspratiquepourcomparerdeuxchanesdecaractresde
manireponctuelle.Cependant,onlui prfreralamthode transform si ungrandnombrede
comparaisonsdoit treeffectu. Eneffet, il est plussimpledetransformertoutesleschanes
decaractresunebonnefoispourtouteset
detravaillerensuitedirectement surleschanes
transformes.Cenestquelorsquelesoprationsdecomparaisonauronttterminesquelon
pourrarevenirsurleschanesdecaractresinitiales.Onviteainsi defairedestransformation
rptitiondeschanescompareretongagneainsi
beaucoupdetemps.Bienentendu,cela
ncessitedeconserverlassociationentreleschanesdecaractrestransformesetleschanes
decaractresinitiales, et doncdedoubler laconsommationmmoireduprogrammedueau
chanesdecaractrespendantletraitementdeceschanes.

Enfin,ilestcourantdechercherdtermineruneclefpourchaquechanedecaractres.Cetteclef
peuttreutilisepoureffectuerunerechercherapidedeschanesdecaractres. Lamthode hash
delafacettecollatepermetdecalculerunetelleclef,engarantissantquedeuxchanesdecaractres
identiquesausensdelamthode compare aurontlammevaleurdeclef.Onnoteracependantque
cetteclefnestpasunique,deuxchanesdecaractrespeuventavoirdeuxvaleursdeclefsidentiques
mmesilamthode compare renvoieunevaleurnonnulle.Cependant,cecasestextrmementrare,
etpermetdutilisermalgrtoutdesalgorithmesderechercherapide.Laseulechoselaquelleilfaut
faireattentionestquecesalgorithmesdoiventpouvoirsupporterlesclefsmultiples.
hash
Note:Lesclefsprobabilitderecouvrementfaiblecommecelleretourneparlamhtode
sontgnralementutilisesdanslesstructuresdedonnesappeles tables de hachage,cequi
expliquelenomdonncettemthode. Lestablesdehachagesont enralitdestableaux
delisteschanesindexsparlaclef dehachage(si lavaleurdelaclef dpasselatailledu
tableau, elleest ramenedansleslimitesdeceluici paruneoprationderduction). Cesont
desstructurespermettant derechercherrapidement desvaleurspourlesquellesunefonction
dehachagesimpleexiste. Cependant, ellessecomportent moinsbienquelesarbresbinaires
lorsquelenombredlmentsaugmente(quelquesmilliers).Onleurprfreradoncgnralement
lesassociationsdelabibliothquestandard, commelesmapet multimapparexemple. Vous
pouvezconsulterlabibliographiesivousdsirezobtenirplusderenseignementssurlestables
dehachageetlesstructuresdedonnesengnral.Lesassociationsetlesconteneursdela
bibliothquestandardserontdcritesdansleChapitre17.

16.2.4.Lesfacettesdegestiondesnombres
Lesoprationsdeformatageetlesoprationsdinterprtationdesdonnesnumriquesdpendentbien
entendudesconventionsnationalesdelalocaleinclusedanslesfluxquieffectuentcesoprations.En
ralit,cesoprationsnesontpasprisesenchargedirectementparlesflux,maispluttparlesfacettes
degestiondesnombres,quiregroupenttouteslesoprationspropresauxconventionsnationales.
Labibliothquestandarddfinit entout troisfacettesqui interviennent danslesoprationsde
formatage:unefacetteutilitaire,quicontientlesparamtresspcifiqueslalocale,etdeuxfacettes
ddiesrespectivementauxoprationsdelectureetauxoprationsdcrituredesnombres.

335

Chapitre16.Leslocales

16.2.4.1.Lafacettenum_punct
Lafacettequiregroupetouslesparamtresdelalocaleestlafacettenum_punct.
commesuitdanslentte locale :

Elleestdclare

template <classcharT>
classnumpunct:publiclocale::facet
{
public:
//Lestypesdedonnes:
typedefcharT
char_type;
typedefbasic_string<charT> string_type;
//Leconstructeur:
explicitnumpunct(size_trefs=0);
//Lesmthodesdelecturedesoptionsdeformatagedesnombres:
char_type
decimal_point() const;
char_type
thousands_sep() const;
string
grouping()
const;
string_type truename()
const;
string_type falsename()
const;
//Lidentificateurdelafacette:
staticlocale::idid;
};

Note:Lesmthodesvirtuellesdimplmentationdesmthodespubliquesnontpastcrites
dansladclarationprcdenteparsoucidesimplification.Ellesexistentmalgrtout,etpeuvent
treredfiniesparlesclassesdrivesafindepersonnaliserlecomportementdelafacette.

Lamthode decimal_point permetdobtenirlecaractrequidoittreutilispoursparerlechiffre


desunitsdeschiffresaprslavirgulelorsdesoprationsdeformatagedesnombresvirgule.
La
.
,
valeurpardfautestlecaractre ,maisenFrance,lecaractreutilisestlavirgule(caractre ).
Demme,lamthode thousands_sep permetdedterminerlecaractrequiestutilispoursparer
lesgroupesdechiffreslorsdelcrituredesgrandsnombres.Lavaleurpardfautrenvoyeparcette
fonctionestlecaractrevirgule(caractre ,),maisdansleslocalesfranaises,onutilisegnrale
mentunespace(caractre ).Enfin,lamthode grouping permetdedterminerlesemplacements
ocessparateursdoiventtreintroduits.Lachanedecaractresrenvoyedterminelenombrede
chiffresdechaquegroupedechiffres.Lenombredechiffresdupremiergroupeestainsistockdans
lepremiercaractredelachanedecaractresrenvoyeparlamthodegrouping,celuidudeuxime
groupeeststockdansledeuximecaractre,etainsidesuite.Lederniernombreainsiobtenudans
cettechanedecaractresestensuiteutilispourtouslesgroupesdechiffressuivants,cequivite
davoirdfinirunechanedecaractresarbitrairementlongue.Unnombredechiffresnulindique
quelemcanismedegroupagedeschiffresdesgrandsnombresestdsactiv.Lesfacettesdelaplu
partdeslocalesrenvoientlavaleur "\03",cequipermetdegrouperleschiffresparpaquetsdetrois
(milliers,millions,milliards,etc.).
Note:Remarquezquelesvaleursstockesdanslachanedecaractresrenvoyeparlamth
ode grouping sontdesvaleursnumriquesetnondeschiffresformatsdanslachanedecar
"\03" etnon "3".
actres.Ainsi,lavaleurpardfautrenvoyeestbien

336

Chapitre16.Leslocales
Lesmthodes truename et falsename quantellespermettentauxfacettesdeformatagedobtenir
leschanesdecaractresquireprsententlesvaleurs true et false desboolens.Cesontceschanes
boolalpha atactivedanslesflux
decaractresquisontutiliseslorsqueloptiondeformatage
dentre/sortie.Lesvaleursretournesparcesmthodessont,pardfaut,lesmotsanglais true et
false.Ilestconcevabledansdautreslocales,cependant,davoirdesnomsdiffrentspourcesdeux
valeurs.NousverronsdanslaSection16.3.2lamaniredeprocderpourredfinircesmthodeset
construireainsiunelocalepersonnaliseetfrancise.
Note:Bienentendu, lesfacettesdcritureet delecturedesnombresutilisent galement les
optionsdeformatagequisontdfinisauniveaudesfluxdentre/sortie.Pourcela,lesoprations
dentre/sortiereoiventenparamtreunerfrencesurlefluxcontenantcesoptions.

16.2.4.2.Lafacettedcrituredesnombres
Lcritureetleformatagedesnombressontprisenchargeparlafacettenum_put.Cettefacetteest
dclarecommesuitdanslentte locale :
template <classcharT,
classOutputIterator=ostreambuf_iterator <charT>>
classnum_put:publiclocale::facet
{
public:
//Lestypesdedonnes:
typedefcharT
char_type;
typedefOutputIteratoriter_type;
//Leconstructeur:
explicitnum_put(size_trefs=0);
//Lesmthodesdcrituredesnombres:
iter_typeput(iter_types,ios_base&f,char_typeremplissage,boolv)const;
iter_typeput(iter_types,ios_base&f,char_typeremplissage,longv)const;
iter_typeput(iter_types,ios_base&f,char_typeremplissage,
unsignedlongv)const;
iter_typeput(iter_types,ios_base&f,char_typeremplissage,
doublev)const;
iter_typeput(iter_types,ios_base&f,char_typeremplissage,
longdoublev)const;
iter_typeput(iter_types,ios_base&f,char_typeremplissage,
void*v)const;
//Lidentificateurdelafacette:
staticlocale::idid;
};

Note:Lesmthodesvirtuellesdimplmentationdesmthodespubliquesnontpastcrites
dansladclarationprcdenteparsoucidesimplification.Ellesexistentmalgrtout,etpeuvent
treredfiniesparlesclassesdrivesafindepersonnaliserlecomportementdelafacette.

337

Chapitre16.Leslocales
Commevouspouvezleconstater,cettefacettedisposedunesurchargedelamthode put pourcha
cundestypesdebasedulangage.Cessurchargesprennentenparamtreunitrateurdcrituresur
lefluxdesortiesurlequellesdonnesformatesdevronttrecrites,
unerfrencesurlefluxde
sortiecontenantlesoptionsdeformatageutiliserlorsduformatagedesnombres, lecaractrede
remplissageutiliser,etbienentendulavaleurcrire.
Engnral,cesmthodessontappelesauseindesoprateursdinsertion operator<< pourchaque
typededonneexistant.Deplus,lefluxdesortiesurlequellescrituresdoiventtreeffectuesest
lemmequelefluxservantspcifierlesoptionsdeformatage, sibienquelappelauxmthodes
put estextrmementsimplifi.Nousverronsplusendtaillamaniredappelercesmthodesdans
laSection16.3.1,lorsquenouscrironsunenouvellefacettepourunnouveautypededonne.

16.2.4.3.Lafacettedelecturedesnombres
Lesoprationsdelecturedesnombrespartirdunfluxdedonnessontprisesenchargeparlafacette
num_get.Cettefacetteestdclarecommesuitdanslentte locale :
template <classcharT,
classInputIterator=istreambuf_iterator<charT>>
classnum_get:publiclocale::facet
{
public:
//Lestypesdedonnes:
typedefcharT
char_type;
typedefInputIteratoriter_type;
//Leconstructeur:
explicitnum_get(size_trefs=0);
//Lesmthodesdelecturedesnombres:
iter_typeget(iter_typein,iter_typeend,ios_base&,
ios_base::iostate&err,bool&v)const;
iter_typeget(iter_typein,iter_typeend,ios_base&,
ios_base::iostate&err,long&v)const;
iter_typeget(iter_typein,iter_typeend,ios_base&,
ios_base::iostate&err,unsignedshort&v)const;
iter_typeget(iter_typein,iter_typeend,ios_base&,
ios_base::iostate&err,unsignedint&v)const;
iter_typeget(iter_typein,iter_typeend,ios_base&,
ios_base::iostate&err,unsignedlong&v)const;
iter_typeget(iter_typein,iter_typeend,ios_base&,
ios_base::iostate&err,float&v)const;
iter_typeget(iter_typein,iter_typeend,ios_base&,
ios_base::iostate&err,double&v)const;
iter_typeget(iter_typein,iter_typeend,ios_base&,
ios_base::iostate&err,longdouble&v)const;
iter_typeget(iter_typein,iter_typeend,ios_base&,
ios_base::iostate&err,void*&v)const;
//Lidentificateurdelafacette:
staticlocale::idid;
};

338

Chapitre16.Leslocales
Note:Lesmthodesvirtuellesdimplmentationdesmthodespubliquesnontpastcrites
dansladclarationprcdenteparsoucidesimplification.Ellesexistentmalgrtout,etpeuvent
treredfiniesparlesclassesdrivesafindepersonnaliserlecomportementdelafacette.

Commevouspouvezleconstater, cettefacetteressemblebeaucouplafacettenum_put. Ilexiste


eneffetunesurchargedelamthode get pourchaquetypedebasedulangage.Cesmthodessont
capablesdeffectuerlalecturedesdonnesdecestypespartirdufluxdentre,entenantcompte
desparamtresdeslocalesetdesoptionsdeformatageduflux.Cesmthodesprennentenparamtre
unitrateurdefluxdentre,unevaleurlimitedecetitrateuraudeldelaquellelalecturedufluxne
seferapas,larfrencesurlefluxdentrecontenantlesoptionsdeformatageetdeuxparamtresde
retour.Lepremierparamtrerecevrauncodederreurdetypeiostatequipourratrepositionndans
lefluxdentrepoursignalerlerreur.Ledeuximeestunerfrencesurlavariabledevantaccueillir
lavaleurlue.Siuneerreurseproduit,cettevariablenestpasmodifie.
Lesmthodes get sontgnralementutilisesparlesoprateursdextraction operator>> desflux
dentre/sortiepourlestypesdedonnesdebasedulangage.Engnral,cesoprateursrcuprent
lalocaleinclusedanslefluxdentresurlequelilstravaillentetutilisentlafacettenum_getdecette
locale. Ilsappellent alorslamthode get permettant delireladonnequilsdoivent extraire, en
fournissantcemmefluxenparamtre.Ilstestentensuitelavariabledtatretourneparlamthode
get et,siuneerreursestproduite,modifientltatdufluxdentreenconsquence.Cettedernire
oprationpeutbienentenduprovoquerlelancementduneexception,selonlemasquedexceptions
utilispourleflux.

16.2.5.Lesfacettesdegestiondesmonnaies
Labibliothquestandardnedfinitpasdetypededonneddislareprsentationdesmontants.Elle
supposeeneffetquelesmontantssontstocksdansdesnombresvirguleflottantedanslaplupart
desprogrammesou,pourlesprogrammesquidsirentsaffranchirdeserreursdarrondisinvitables
lorsdelutilisationdeflottants,sousformetextuelledansdeschanesdecaractres.Enrevanche,la
bibliothquestandardfournit,toutcommepourlestypesstandards,deuxfacetteslocalisesprenant
encomptelalectureetlcrituredesmontants. Cesfacettessebasentgalementsurunetroisime
facettequiregroupetouslesparamtresspcifiquesauxconventionsnationales.
Note:Enralit,lesseulstypescapablesdereprsentercorrectementlesmontantseninfor
matiquesontlesentiersetlesnombresvirgulefixecodssurlesentiers. Eneffet, lestypes
intgrauxsontlesseulstypesquinesoulventpasdeproblmedereprsentationdesnombres
(conditionquil nyaitpasdedbordementsbienentendu)etlesnombresvirgulefixesont
particulirementadaptsauxmontants,carengnrallenombredechiffressignificatifsaprsla
virguleestfixpourunemonnaiedonne.Lesnombresvirguleflottantenepermettentpasde
reprsenterdesvaleursavecprcisionetintroduisentdeserreursincontrlablesdanslescalculs
etdanslesarrondis.Leschanesdecaractresquantellessouffrentdeleurlourdeuret,dans
laplupartdescas,delancessitdepasserpardesnombresvirguleflottantespourinterprter
leurvaleur. Lesfacettesprsentesdanscettesectionsont doncduneutilitrduitepourles
programmesqui cherchentobtenirdesrsultatsrigoureuxetprcis,etqui netolrentpasles
erreursdereprsentationetleserreursdarrondis.

Touteslesfacettesdegestiondesmontantssontdesclasses template. Cependant, contrairement


template queletypedecaractre
auxautresfacettes,cesfacettesdisposentdunautreparamtre
surlequelellestravaillent.Ceparamtreestunparamtredetypeboolenquipermet,selonsavaleur,

339

Chapitre16.Leslocales
despcifiersilesfacettesdoiventtravailleraveclareprsentationinternationaledesmontantsounon.
Ilexisteeneffetunereprsentationuniverselledesmontantsqui,entreautresparticularits,utiliseles
codesinternationauxdemonnaie(USDpourledollaramricain,CANpourledollarcanadien,
EURpourleuro,etc.).
Commepourlesfacettesdegestiondesnombres, lesfacettesprenantenchargelesmonnaiessont
aunombredetrois.Unedecestroisfacettespermetdobtenirdesinformationssurlamonnaiedela
localeetlesdeuxautresralisentrespectivementlesoprationsdcritureetdelecturesurunflux.

16.2.5.1.Lafacettemoney_punct
Lafacettemoneypunctestlafacettepermettantauxdeuxfacettesdcritureetdelecturedesmontants
dobtenirlesinformationsrelativeslamonnaiedeleurlocale.Cettefacetteestdclarecommesuit
danslentte locale :
template <classcharT,boolInternational=false
>
classmoneypunct:publiclocale::facet,publicmoney_base
{
public:
//Lestypesdedonnes:
typedefcharTchar_type;
typedefbasic_string<charT> string_type;
//Leconstructeur:
explicitmoneypunct(size_trefs=0);
//Lesmthodesdelecturedesoptionsdeformatagedesmontants:
charT
decimal_point()const;
charT
thousands_sep()const;
string
grouping()
const;
int
frac_digits() const;
string_typecurr_symbol() const;
pattern
pos_format()
const;
pattern
neg_format()
const;
string_typepositive_sign()const;
string_typenegative_sign()const;
staticconstboolintl=International;
//Lidentificateurdelafacette:
staticlocale::idid;
};

Note:Lesmthodesvirtuellesdimplmentationdesmthodespubliquesnontpastcrites
dansladclarationprcdenteparsoucidesimplification.Ellesexistentmalgrtout,etpeuvent
treredfiniesparlesclassesdrivesafindepersonnaliserlecomportementdelafacette.

Commevouspouvezleconstater,cettefacettedisposedemthodespermettantdercuprerlesdi
verssymbolesquisontutilisspourcrirelesmontantsdelamonnaiequelledcrit.Ainsi,lamthode
decimal_point renvoielecaractrequidoittreutilisentantquesparateurduchiffredesuni
tsdelapartiefractionnairedesmontants, sicelleci doit trereprsente. Demme, lamthode
thousands_sep renvoielecaractrequidoittreutilispoursparerlesgroupesdechiffrespour

340

Chapitre16.Leslocales
lesgrandsmontants,etlamthode grouping renvoieunechanecontenant,danschacundesesca
ractres,lenombredechiffresdechaquegroupe.Cesmthodessontdoncsemblablesauxmthodes
correspondantesdelafacettenumpunct. Lenombredechiffressignificatifsaprslavirguleutilis
frac_digits. Cenestquesilavaleur
pourcettemonnaiepeuttreobtenuegrcelamthode
renvoyeparcettemthodeestsuprieure0quelesymboledesparationdesunitsdelapartie
fractionnairedelamthode decimal_point estutilis.
Lamthode curr_symbol permetdobtenirlesymbolemontairedelamonnaie.Cesymboledpend
delavaleurduparamtre templateInternational.Siceparamtrevaut true,lesymbolemo
ntairerenvoyseralesymbolemontaireinternational.Danslecascontraire,ceseralesymbolemo
ntaireenusagedanslepaysdecirculationdelamonnaie.Lavaleurduparamtre International
pourratreobtenugrcelaconstantestatique intl delafacette.
Lesmthodessuivantespermettentdespcifierleformatdcrituredesmontantspositifsetngatifs.
Cesmthodesutilisentlesdfinitionsdeconstantesetdetypesdelaclassedebasemoney_basedont
lafacettemoneypuncthrite.Laclassemoney_baseestdclarecommesuitdanslenttelocale :
classmoney_base
{
public:
enumpart
{
none,space,symbol,sign,value
};
structpattern
{
charfield[4];
};
};

Cetteclassecontientladfinitiondunenumrationdontlesvaleurspermettentdidentifierlesdif
frentescomposantesdunmontant,ainsiquunestructurepatternquicontientuntableaudequatre
caractres.Chacundecescaractrespeutprendrelunedesvaleursdelnumrationpart.Lastructure
patterndfinitdonclordredanslequellescomposantesdunmontantdoiventapparatre.Cesontdes
motifsdecegenrequisontrenvoysparlesmthodes pos_format et neg_format,quipermettent
dobtenirrespectivementleformatdesmontantspositifsetceluidesmontantsngatifs.
Lesdiffrentesvaleursquepeuventprendreleslmentsdumotifpatternreprsententchacuneune
partiedelexpressiondunmontant.Lavaleurvalue reprsentebienentendulavaleurdecemontant,
sign sonsigneet symbol lesymbolemontaire.Lavaleur space permetdinsrerunespacedans
lexpressiondunmontant,maislesespacesnepeuventpastreutilissendbutetenfindemontants.
Enfin,lavaleur none permetdenerienmettrelapositionoilapparatdanslemotif.
Lamaniredcrirelesmontantspositifsetngatifsvariegrandementselonlespays.
Engnral,
ilestcourantdutiliserlesigne poursignalerunmontantngatifetaucunsignedistinctifpour
lesmontantspositifs.Cependant,certainspayscriventlesmontantsngatifsentreparenthsesetla
marquedesmontantsngatifsnestdoncplusunsimplecaractre.Lesmthodes positive_sign
et negative_sign permettentdobtenirlessymbolesutiliserpournoterlesmontantspositifset
ngatifs.Ellesretournenttouteslesdeuxunechanedecaractres,dontlepremierestplacsystma
tiquementlemplacementauquellavaleur sign ataffectedanslachanedeformatrenvoye
parlesmthodes pos_format et neg_format.Lescaractresrsiduels,silsexistent,sontplacs
lafindelexpressiondumontantcompltementformate.Ainsi,dansleslocalespourlesquellesles
montantsngatifssontcritsentreparenthses,lachanerenvoyeparlamthode negative_sign

341

Chapitre16.Leslocales
est () , etpourleslocalesutilisantsimplementlesignengatif,
caractre .

cettechanenecontientquele

16.2.5.2.Lesfacettesdelectureetdcrituredesmontants
Lesfacettesdcritureet delecturedesmontantssont sansdoutelesfacettesstandardslesplus
simples. Eneffet, ellesnedisposent quedemthodespermettant dcrireet delirelesmontants
surlesflux.Cesfacettessontrespectivementlesfacettesmoney_putetmoney_get.Ellessontdfinies
commesuitdanslentte locale :
template <classcharT,boolIntl=false,
classOutputIterator=ostreambuf_iterator <charT>>
classmoney_put:publiclocale::facet
{
public:
//Lestypesdedonnes:
typedefcharT
char_type;
typedefOutputIterator
iter_type;
typedefbasic_string<charT> string_type;
//Leconstructeur:
explicitmoney_put(size_trefs=0);
//Lesmthodesdcrituredesmontants:
iter_typeput(iter_types,boolintl,ios_base&f,
char_typeremplissage,longdoubleunits)const;
iter_typeput(iter_types,boolintl,ios_base&f,
char_typeremplissage,conststring_type&digits)const;
//Lidentificateurdelafacette:
staticlocale::idid;
};
template <classcharT,
classInputIterator=istreambuf_iterator<charT>>
classmoney_get:publiclocale::facet
{
public:
//Lestypesdedonnes:
typedefcharT
char_type;
typedefInputIterator
iter_type;
typedefbasic_string<charT> string_type;
//Leconstructeur:
explicitmoney_get(size_trefs=0);
//Lesmthodesdelecturedesmontants:
iter_typeget(iter_types,iter_typeend,bool