Vous êtes sur la page 1sur 187

Formation C++ avancee

ou comment etre les stars du C++


Raffi Enficiaud
INRIA
16-18 fevrier 2009
INRIA - IMEDIA
Formation C++ avancee
Organisation generale
Enciaud (INRIA) C++ 16-18/02/2009 2 / 201
`
A qui sadresse-t-elle ?
Public
`
A tout developpeur C++ ayant idealement quelques mois (annees) dexperience.
Prerequis
La personne doit savoir manipuler le C++, ou en tout cas le C+-(C++ fa con C)
Enciaud (INRIA) C++ 16-18/02/2009 3 / 201
Th`emes de la formation
1
vous permettre detre le plus autonome possible avec le C++

Mieux comprendre certaines subtilitesdu langage

Mieux comprendre ce que gen`ere le compilateur `a partir du code que vous


ecrivez
2
vous rendre plus productif avec les mecanismes du C++

Utiliser le compilateur pour faire des evolutions incrementales

Travailler en equipe

Identier plus precisement les sources potentielles de bug

Mettre en place des mecanismes de contr ole de fonctionnalite et devolution

Sintegrer au mieux `a un monde exterieur`a votre (partie de) programme


Enciaud (INRIA) C++ 16-18/02/2009 4 / 201
Deroulement
3 jours intenses de formation :)
Jour 1
Cafe
Cafe
Rappel des bases du C++ (+ exercices)
(Mini) etude de cas
Jour 2
Les templates (+ exercices)
La STL (+ exercices)
La programmation generique (+ exercices)
Les patrons de conception (+ exercices)
Jour 3
Organisation de code dans les grandsprogrammes
Utilisation de Boost
Enciaud (INRIA) C++ 16-18/02/2009 5 / 201
Formation C++ avancee
J1 : C++ avance
Enciaud (INRIA) C++ 16-18/02/2009 6 / 201
J1 : C++ avance
Contenu
1
Quelques dicultes du langage
2
Rappels sur les instructions
3
Classes
4
Heritage
5
Exceptions structurees
6
Etude de cas
Enciaud (INRIA) C++ 16-18/02/2009 7 / 201
Quelques dicultes
du langage
Enciaud (INRIA) C++ 16-18/02/2009 8 / 201
Subtilite ?
Exemples...
Syntaxe pas trop dicile
Fonctionnalites importantes

Langage dicile
Boucle for
1 i n t i ;
2 f or ( i n t i = 0; i < 100; ++i ) {
3 }
References
Class A Utilisation de A
1 c l a s s A {
2 s t d : : s t r i n g &s ;
3 publ i c :
4 A( s t d : : s t r i n g s ) : s ( s ) {}
5 const s t d : : s t r i n g& gi ve me s ( ) const { r et ur n
s ; }
6 };
1 A a ( "toto" ) ;
2 a s s e r t ( a . gi ve me s ( ) == "toto" ) ; // a s s e r t
t hr ows or bug
Enciaud (INRIA) C++ 16-18/02/2009 9 / 201
Rappels sur les
instructions
Types
struct
union
POD
typedef
extern
Controle
Pointeurs
Reference
Garantie de non modication : const
Espace de nom
Pointeurs sur fonction
References sur fonction
volatile
Enciaud (INRIA) C++ 16-18/02/2009 10 / 201
Chanes de caract`ere
Meme l`a-dessus il faut revenir...
Plusieurs types de chane de caract`ere :
Declaration :
1
Chane de type classique: char
2
Chane de type etendu international: wchar t
Le type international est souvent utile pour ce qui concerne le syst`eme de chier,
les messages utilisateurs, etc...
1 char s c o ns t a nt = "blablabla" ;
2 wchar t s wi de = L"wide blablabla" ;
Preprocesseur :
Concat`ene automatiquement les chanes de caract`eres qui se suivent :
1 char t ot o = "One big string split " "among small strings"
2 " and among many lines"
3 "... " ;
Enciaud (INRIA) C++ 16-18/02/2009 12 / 201
Mot clef enum
Denition (enum)
Les enum denissent un ensemble (reduit) de valeurs.
Les enums sont des entiers (constant), mais les entiers ne sont pas des enums.
1 enum e my enum { // enum nomme e my enum
2 val 1 , // par de f aut = 0
3 val 2 , // par de f aut = 1
4 v a l 4 = 4 // v a l 4 f o r c e `a 4
5 };
6
7 enum { // enum anonyme
8 u 1 ,
9 u 2 ,
10 } e1 , e2 ; // et dont e1 et e2 s ont des i n s t a n c e s
11
12 t ypedef /enum/ e my enum my s e t e l e me nt s ;
13
14 voi d f unc (enum e my enum e ) ;
15 voi d f unc2 ( my s e t e l e me nt s e ) ;
Enciaud (INRIA) C++ 16-18/02/2009 13 / 201
Structures
Denition (struct(ou structure))
Une structure est une agregation delements
La structure est lancetre de lobjet...
Structure nommee Structure anonyme
1 s t r uc t A { // s t r u c t u r e nommee A ( f a c u l t a t i f )
2 i n t i ; // C
3 i n t j ;
4 pr i v a t e : // C++
5 i n t p ;
6 };
7 A a ;
8 a . i = 10; // ok
9 a . o = 20; // ac c`e s i mp o s s i b l e
1 s t r uc t { // s t r u c t u r e anonyme
2 i n t i ;
3 f l o a t f ;
4 } b , c ; // b et c en s ont des i n s t a n c e s
5 b . i = c . i = 10;
6 b . f = c . f = 20. f ;
Il ny a aucune dierence fonctionnelle entre une structure et une classe.
Par compatibilite avec le C, lacc`es par defaut est public (cf. partie sur les classes)
Enciaud (INRIA) C++ 16-18/02/2009 14 / 201
Union
Denition (union)
Une union est une structure particuli`ere, nutilisant quun type `a la fois.
Union
Declaration Utilisation
1 uni on u {
2 i n t a ;
3 i n t j ;
4
5 pr i v a t e : // C++
6 i n t p ;
7 };
1 s t r uc t A uni on {
2 uni on unnamed uni on {
3 s t d : : s t r i n g s ;
4 const char p ;
5 doubl e d ;
6 unnamed uni on ( ) : d ( 3. 14) {}
7 } c u r r e n t v a l u e ;
8
9 enum enum type {
10 e s t r i n g ,
11 e char ,
12 e f l o a t
13 } c u r r e n t t y p e ;
14
15 A uni on ( enum type e = e f l o a t ) : p(
c u r r e n t t y p e ) , c u r r e n t t y p e ( e ) ,
c u r r e n t v a l u e ( ) {}
16 A uni on ( ) {
17 }
18
19 };
Il ny a aucune dierence fonctionnelle entre une structure et une classe.
Par compatibilite avec le C, lacc`es par defaut est public.
Enciaud (INRIA) C++ 16-18/02/2009 15 / 201
Types POD
Les types natifsou agregation de type natif
Denition (POD)
POD = Plain Old Data
Plus precisement, tout type ayant un equivalent direct avec le C, concernant
linitialisation, la taille, et ladressage :
toute valeur numerique (bool, int, double...)
les enums et les unions
les structures sans aucun constructeur, operateur dattribution, classe de
base, methode virtuelle, variable non-statique non publique, etc.
Enciaud (INRIA) C++ 16-18/02/2009 16 / 201
Mot clef typedef
Denition (typedef)
Cree un alias entre une designation compl`ete et un nom.
1 t ypedef s t r uc t s my s t r uc t t ot o ;
2 t ypedef s t d : : vect or <i nt > i n t v e c t o r ;
Les alias ne prennent aucune tailleau moment de lexecution.
Generalement, les typedefs permettent davoir un code plus concis, et dans
certains cas daccelerer les temps de compilation (template).
Nous verrons quelques utilisations du mot clef typedefpendant la partie sur les
templates.
Enciaud (INRIA) C++ 16-18/02/2009 17 / 201
Mot clef extern
Denition (extern)
Directive indiquant la denition dun objet alloue exterieurement(ailleurs que la
ligne indiquant sa denition).
Les declarations de fonction sont extern par defaut (par opposition `a static )
Il est possible davoir une declaration extern suivie de la declaration concr`ete
1 ext er n s t d : : s t r i n g s ; // ambi gu te e nt r e de c l a r a t i o n et s t ockage
2 s t d : : s t r i n g s ; // l e ve e par l e mot c l e f e x t e r n
3 voi d f unc t i on1 ( ) ; // de c l a r a t i o n par de f aut e x t e r n
4 voi d f unc t i on1 ( ) {} // de c l a r a t i o n du c or ps de l a f o n c t i o n
extern designe egalement externe au corps courant
1 voi d f unc ( i n t i ) {
2 ext er n A a1 , a2 , a3 ; // v a r i a b l e s e x t e r ne s au c or ps de f unc
3 s wi t ch ( i ) {
4 case 1: a1++; br eak ;
5 case 2: a2++; br eak ;
6 de f a ul t : a3++; br eak ;
7 }}
8 A a1 , a2 , a3 ;
Enciaud (INRIA) C++ 16-18/02/2009 18 / 201
Contr ole
Boucles for
1 f or ( i n t i = 0; i < 100; i ++)
La variable iest interne au bloc for. Les ;denissent les champs : il est possible
de ne pas les initialiser :
1 i n t i = 0;
2 f or ( ; i < 100; i ++)
Enciaud (INRIA) C++ 16-18/02/2009 19 / 201
Pointeurs
Denition
Denition (pointeur)
Un pointeur est une variable designant un autre objet (lobjet pointe)
Le type du pointeur contient le type de lobjet pointe
Le fait dacceder `a lobjet pointe est le deferencement du pointeur.
La valeur 0(zero) est lequivalent C++ de la macro C NULL. Elle permet de
specier quun pointeur na pas ete initialise !
1 i n t p ; // po i nt e ur poi nt a nt s ur un e n t i e r ( non i n i t i a l i s e , vaut n i mpor t e quoi et donc e v e nt ue l l e me nt
s ur des donnees e x i s t a n t e s )
2 i n t u ( 0) ; // p a r e i l , mai s i n i t i a l i s e `a 0 ( ne poi nt e s ur r i e n , meme JAMAIS s ur des donnees e x i s t a n t e s )
3 i n t i = 10;
4 p = 20; // BUG HORRIBLE c ar ne s e mani f e s t e p a r f o i s pas
5 p = &i ; // p pr end l a dr e s s e de i
6 a s s e r t (p == i ) ; // def er encement de p
7 p = u ; // BUG PAS HORRIBLE c ar s e mani f e s t e TOUT LE TEMPS !
Enciaud (INRIA) C++ 16-18/02/2009 20 / 201
Reference
Denition
Denition (Reference)
Ref`ere un objet existant : alias sur lobjet refere (la reference est lobjet refere)
Attention !
Une reference est une variable
Mais la variable ne peut pas changer dobjet refere (contrairement `a un
pointeur).
Une variable reference doit toujours etre initialisee lors de sa construction.
1 i n t a = 0 , b = 1;
2 i n t &r e f a = a ;
3 s t d : : cout << "ref_a = " << r e f a << s t d : : e ndl ;
4
5 r e f a = b ;
6 s t d : : cout << "ref_a = " << r e f a << s t d : : e ndl ;
7 s t d : : cout << "but the value of a is now = " << a << s t d : : e ndl ;
Enciaud (INRIA) C++ 16-18/02/2009 21 / 201
Mot clef const
Denition
Denition (const)
Mot clef indiquant que lobjet est constant (non mutable ie. non modiable).
Un objet constant ne peut etre pointe ou refere par une variable rompant la
constance de lobjet pointe ou refere.
1 i n t const a = 0 , b = 1;
2 // i n t &r e f a = a ; // e r r e ur , r e f a ne g a r a n t i e pas que a e s t c ons t ant
3 i n t const &r e f a = a ;
4 const i n t &r e f b = b ;
5
6 // i n t p a = &a ; // e r r e ur , p a ne g a r a n t i e pas que a e s t c ons t ant
7 i n t const p a = &a ;
Nous verrons plus tard que, pour un objet, seules des methodes assurant la
constance de lobjet peuvent etre appelees.
Enciaud (INRIA) C++ 16-18/02/2009 22 / 201
Mot clef const
Utilisation des pointeurs
const int et int constsont semantiquement equivalents.
const int et int const sont donc deux pointeurs sur un entier
constant (le const est avant l).
Ne pas confondre
const int , int const et int const
1 const i n t a ;
2 i n t b , c ;
3 const i n t p a = &a ; // po i nt e ur s ur un e n t i e r c ons t ant
4 i n t const p b = &b ; // po i nt e ur c ons t ant s ur un e n t i e r ( l a v a r i a b l e po i nt e ur ne peut pas e t r e change )
5
6 p a = &b ; //ok
7 p b = &c ; // e r r e ur , p b ( v a r i a b l e ) e s t c ons t ant
Rappel : Une variable reference est toujours constante
int & const na pas tellement de sens (identique `a int &).
Enciaud (INRIA) C++ 16-18/02/2009 23 / 201
Mot clef namespace
Denition & syntaxe
Denition (namespace)
Permet de separer un ensemble de denitions, types, fonctions... du reste du
monde(inclusion de librairies/headers externes par exemple).
1 namespace ns1 {
2 i n t const a = 0 , b = 1;
3 bool f o nc t i o n1 ( i n t i , i n j ) ;
4 }
5
6 namespace ns2 {
7 i n t const a = 0 , b = 1;
8 bool f o nc t i o n1 ( i n t i , i n j ) ;
9 namespace ns22 {
10 voi d f o nc t i o n1 ( f l oa t , f l o a t ) ;
11 }
12 }
13 // Ut i l i s a t i o n
14 ns2 : : f o nc t i o n1 ( ns1 : : a , ns2 : : b) ;
Enciaud (INRIA) C++ 16-18/02/2009 24 / 201
Mot clef namespace
Usage
Alias de namespace
Il est possible davoir un alias sur un namespace
1 namespace NS = ns2 : : ns22 ;
2 NS : : f o nc t i o n1 ( 0. 32 f , 0. 31 f ) ;
Namespace implicite
Il est possible de dire au compilateur daller chercher dans un namespace de
mani`ere automatique :
1 us i ng namespace ns2 : : ns22 ;
2 f o nc t i o n1 ( 0. 32 f , 0. 31 f ) ;
Attention `a cette derni`ere fonctionnalite : le cote implicite est souvent source
derreurs.
Enciaud (INRIA) C++ 16-18/02/2009 25 / 201
Pointeurs sur fonction
Rappels
Denition (et usage)
Permet de stocker ladresse dune fonction dans une variable (lattribution de cette
variable pouvant etre donne par une fonction).
La variable peut ensuite (bien-s ur) etre utilisee pour appeler la fonction sur
laquelle elle pointe.
1 bool f unc2 ( const doubl e &, i nt , f l o a t &) ;
2 voi d f unc1 ( bool (t ot o ) ( const doubl e &, i nt , f l o a t &) ) {
3 // De c l a r a t i o n de l a v a r i a b l e t ot o , comme e t ant un po i nt e ur
4 // s ur une f o n c t i o n de t ype bool ( cons t doubl e &, i nt , f l o a t &)
5 f l o a t r e t u r n e d f ;
6
7 i f ( t ot o ( 0. 39 , 42 , r e t u r n e d f ) )
8 s t d : : cout << "function returned true and the float is = to" << r e t u r n e d f << s t d : : e ndl ;
9 e l s e
10 s t d : : cout << "function returned false" << s t d : : e ndl ;
11 }
12 f unc1 ( 0) ; // e r r e u r `a l e xe c ut i on ( l o r s de l appe l `a t ot o ) : f o n c t i o n n u l l e
13 f unc1(&f unc2 ) ; // a t t r i b u t i o n de t ot o `a f unc2
Enciaud (INRIA) C++ 16-18/02/2009 26 / 201
References sur fonction
Denition (et usage)
Permet de stocker la reference dune fonction dans une variable (lattribution de
cette variable pouvant etre donne par une fonction).
Contrairement au pointeur, la reference sur fonction est non-mutable
(re-assignation de la reference impossible).
1 bool f unc2 ( const doubl e &, i nt , f l o a t &) ;
2 voi d f unc1 ( bool (&var ) ( const doubl e &, i nt , f l o a t &) ) {
3 // De c l a r a t i o n de l a v a r i a b l e t ot o , comme e t ant une r e f e r e n c e
4 // s ur une f o n c t i o n de t ype bool ( cons t doubl e &, i nt , f l o a t &)
5 f l o a t r e t u r n e d f ;
6
7 i f ( var ( 0. 39 , 42 , r e t u r n e d f ) )
8 s t d : : cout << "function returned true and the float is = to" << r e t u r n e d f << s t d : : e ndl ;
9 e l s e
10 s t d : : cout << "function returned false" << s t d : : e ndl ;
11 }
12 f unc1 ( 0) ; // e r r e u r `a l a c ompi l a t i on : f o n c t i o n n u l l e n e x i s t e pas
13 f unc1 ( f unc2 ) ; // a t t r i b u t i o n de t ot o `a f unc2
Enciaud (INRIA) C++ 16-18/02/2009 27 / 201
Mot clef volatile
Denition (volatile)
volatile est un modicateur
a
indiquant au compilateur que la variable doit
etre lue en memoire `a chaque acc`es.
a. modie le comportement par defaut dun type
Ce modicateur a ete initialement utilise pour permettre des acc`es `a des variables
externes au processeur sur lequel le programme sexecute (chip annexe par
exemple). Il indique au compilateur, en outre, que la variable en question ne
participe pas `a des optimisations (inferences sur sa valeur).
Pour ceux/celles qui utilisent les threads, ce modicateur doit etre utilise pour les
variables dont lacc`es se fait via des threads concurrents.
Enciaud (INRIA) C++ 16-18/02/2009 28 / 201
Exercice
Fonction retournant un repertoire temporaire
On souhaite avoir une fonction, temporary path, qui retourne une chane
representant le chemin complet dun repertoire temporaire.
On souhaite en outre :
1
que le chemin temporaire soit lu `a partir de la variable denvironnement
TEMP. Pour cela, on utilisera la fonction C/ANSI std :: getenv(dans
<cstdlib>) qui prend en param`etre le nom de la variable denvironnement
et qui retourne char . Ce retour peut valoir NULLsi la variable
denvironnement nexiste pas.
2
on souhaite que cette variable ne soit lue quune seule fois, de mani`ere `a
reduire lacc`es co uteux`a lenvironnement.
3
si cette variable nexiste pas, on ne veut pas que notre programme plante. On
initialisera la variable au repertoire contenant le chier compile (cest super
laid, mais cest juste `a titre dexemple)
1
. Pour cela on se servira de la macro
C/ANSI FILE , de std :: string et de std: string :: rnd (on cherchera
le . `a partir de la n).
4
on veut pouvoir modier ce repertoire temporaire de la mani`ere suivante :
1 t empor ar y pat h ( ) = "mon_nouveau_repertoire" ;
Indice : il sagit dune initialisation de type statique, `a laide dune fonction
retournant la chane quon souhaite.
Exposez le prototype dans un chier .hpp, et cacher limplementation compl`ete
dans un chier .cpp.
Faire un petit main de test.
1. Boost permettra de faire du code portable, pour linstant on na pas le choix
Enciaud (INRIA) C++ 16-18/02/2009 29 / 201
Classes
Attributs membres
Methodes membres
Attributs statiques
Methodes statiques
Attributs mutables
Champs membres
this
Pointeur sur membres
Constructeurs de classe
Destructeurs
Surcharge doperateurs
Operateurs arithmetiques
Operateur dattribution
Operateur de conversion
Operateur de fonction
Enciaud (INRIA) C++ 16-18/02/2009 30 / 201
Classe
Denition
Denition (Classe)
Une classe declare des proprietes communes `a un ensemble dobjets. Elle denie
des attributs (variables membres) representant letat des objets, et des methodes
denissant leurs comportements.
Denition (Instance)
Une instance de classe est un objet suivant la denition de la classe, et dont les
variables membres ont une valeur.
Enciaud (INRIA) C++ 16-18/02/2009 31 / 201
Classe
Denition (2)
La classe est lelement central de la programmation orientee objet. Lobjet est une
instance de classe.
Rappel
Il ny a pas de dierence entre une classe et une structure.
1 // De c l a r a t i o n d une c l a s s e
2 c l a s s A {
3 publ i c :
4 i n t i ;
5 f l o a t j ;
6
7 A( ) {} // f a b r i q u e / c o n s t r uc t e u r ( par de f aut )
8
9 voi d eval uat eMe ( ) const ; // methode membre
10 };
11
12
13 A a ; // de c l a r a t i o n d une i n s t a n c e de c l a s s e A
Enciaud (INRIA) C++ 16-18/02/2009 32 / 201
Classe
Declaration & Syntaxe
La declaration est donne par la directive class ou struct
Elle est suivie eventuellement du corps de la classe (accolades)
Elle se termine par un ;
Si le corps est deni, il est possible de declarer des objets :
1 c l a s s A {} a , b , c ;
2 s t r uc t B {/ . . . /} d , e , f ;
Si le corps nest pas deni, la directive declare une classe dont le corps est
inconnu. Puisque le corps est inconnu, il est impossible de declarer des objets de
cette classe :
1 c l a s s A;
2 A a ; // e r r e u r : l a t a i l l e de a e s t i nconnue
3 A a ; // ok : l a t a i l l e du po i nt e ur et son t ype s ont connus
Le corps de la classe denie ses membres. Une fois le corps termine, il nest pas
possible dajouter des membres.
Enciaud (INRIA) C++ 16-18/02/2009 33 / 201
Classe
Attributs membres
Denition (attribut)
Les attributs denissent le contenu des classes.
Les attributs participent directement `a la taille occupee en memoire par la classe.
1 s t r uc t A {
2 bool v al ue ;
3 bool& get Val ue ( ) ; // de c l a r a t i o n de l a methode get Val ue
4 bool get Val ue ( ) const ; // de c l a r a t i o n de l a methode get Val ue cons t
5 };
Enciaud (INRIA) C++ 16-18/02/2009 34 / 201
Classe
Methodes
Denition (methodes)
Les methodes denissent le comportement des classes.
Le corps de la classe doit contenir la declaration ou la denition compl`ete de
la methode membre.
Les methodes ne participent quexceptionnellement (cf. heritage) `a la place
occupee en memoire par la classe
Elle indiquent egalement si leur appel modie la classe (ie. si la classe est
mutableou non).
1 s t r uc t A {
2 bool v al ue ;
3 bool& get Val ue ( ) ; // de c l a r a t i o n de l a methode get Val ue
4 bool get Val ue ( ) const ; // de c l a r a t i o n de l a methode get Val ue cons t
5 };
Il est possible de denir les methodes membres `a linterieur du corps de la classe :
il deviennent alors inline (declarable dans un header par exemple).
Enciaud (INRIA) C++ 16-18/02/2009 35 / 201
Classe
Attributs static
Denition (static)
Variable membre non liee `a une instance particuli`ere, et partagee par toutes les
instances dune classe.
Il faut linitialiser de la meme mani`ere quune variable statique normale, et en
dehors du corps de la classe
Sauf pour un entier constant, ou un enum, qui peut etre initialise `a linterieur
du corps de la classe
La syntaxe impose la declaration dans le corps de la classe, et
lattribution/initialisation `a lexterieur du corps de la classe. Attention aux
acc`es concurrentiels.
Compteur dinstance
1 s t r uc t A {
2 s t a t i c i n t nb i ns t a nc e ;
3 A ( ) { nb i ns t a nc e ++;}
4 };
5 i n t A: : nb i ns t a nc e = 0;
Enciaud (INRIA) C++ 16-18/02/2009 36 / 201
Classe
Methodes statiques
Denition (Statique)
Methode dune classe non liee `a une instance particuli`ere, et partagee par toutes
les instances.
1
Utilisable par toutes les instances dune classe
1 pas besoin dune instance pour appeler la methode
2 impossible dattribuer un modicateur const`a la methode
2
Acc`ede `a tous les autres membres statiques de la classe
3
Acc`ede `a tous les membres non statiques de le classe, si on lui fournit un
pointeur sur linstance courante (this)
factory(ie. fabrique) de classe
1 s t r uc t A {
2 s t a t i c i n t nb i ns t a nc e ; // de c l a r a t i o n de l a t t r i b u t s t a t i c
3 s t a t i c i n t NbI ns t ances ( ) { r et ur n nb i ns t a nc e ; } // d e f i n i t i o n
4 s t a t i c A c r e a t e ( ) ; // de c l a r a t i o n s e u l e
5 };
6 A A: : c r e a t e ( ) {
7 nb i ns t a nc e ++; r et ur n A;
8 }
Enciaud (INRIA) C++ 16-18/02/2009 37 / 201
Classe
Attributs mutable
Denition (mutable)
Variable membre non static et non const, qui ne participe pas `a la gestion du
const de la classe.
La modication dune variable mutable est autorisee `a partir dune methode
const.
1 s t r uc t A {
2 mutabl e i n t v al ue ;
3 i n t get Val ue ( ) const { r et ur n v al ue ++; }
4 };
Les variables mutablepermettent de cacher certains details dimplementation
(ex. mecanisme de cache).
Enciaud (INRIA) C++ 16-18/02/2009 38 / 201
Classe
Contr ole dacc`es
Dans le corps de la classe, on attribut `a chaque membre une restriction sur
lacc`es, parmi :
public : le membre est visible de tout le monde
protege (protected) : le membre nest visible que dune classe lle (cf.
heritages)
prive (private) : le membre nest visible que dune instance strictement du
meme type (qui peut etre linstance courante)
Par defaut, une class a une visibilite privee, alors quune struct a une visibilite
publique (compatibilite avec le C).
1 c l a s s A {
2 i n t i p r i v a t e ; // p r i ve
3 voi d me t hod pr i vat e ( ) ;
4 publ i c :
5 i n t i p u b l i c ;
6 voi d method ( ) ;
7 } ;
Enciaud (INRIA) C++ 16-18/02/2009 39 / 201
Classe
Champs membres
Denition (champ)
La denition dun type par lutilisation de linstruction typedef.
1 s t r uc t A {
2 t ypedef A t h i s t y p e ;
3 t ypedef s t d : : vect or <i nt > s t o r a g e t y pe ;
4 t ypedef s t o r a g e t y pe : : v a l ue t y pe v a l ue t y pe ;
5 / . . . /
6 };
Les champs de type sont valides `a linterieur de lespace de nom de la classe.
Rappel : les champs de type ne prennent aucune place en memoire, et donc ne
participent pas `a la taille occupee en memoire par la classe.
Enciaud (INRIA) C++ 16-18/02/2009 40 / 201
Classe
Mot clef this
Denition (this)
thispointe sur linstance courante
1 s t r uc t A {
2 i n t i ; f l o a t f ;
3 voi d Addi t i on ( const A& r ) {
4 t hi s >i += r . i ;
5 t hi s >j += r . j ;
6 }
7 } a1 , a2 ;
Sauf...
Avant que la classe ne soit compl`etement construite : par exemple avant dentrer
dans le constructeur.
Nous verrons ce dernier point pendant les constructeurs.
Enciaud (INRIA) C++ 16-18/02/2009 41 / 201
Exercice
Decomposition en nombres premiers
Objectif
Avoir une classe, decomposed primes, decomposant un entier en puissances de
nombres premiers.
1
un champ return typeprecisera le type de stockage. Il sera du type map
2
la methode decomposeprendra un entier en entree, et retournera
return type
3
une liste initiale de nombre premiers sera denie au lancement du programme
(note : variable statique)
4
la classe aura une memoirecachee, lui permettant dajouter des nombres
premiers `a sa liste initiale
5
pour plus de performances, la classe stockera la decomposition en nombre
premiers des nombres inferieurs `a 100.
On se servira du type cache, std :: map<int,int>(tableau associatif), pour stocker une decomposition. On se servira du type cache, std :: set<int>
(ensemble ordonne), pour stocker les nombres premiers dans lordre croissant.
On saidera des chiers decomposed primes.[h|cpp].
Enciaud (INRIA) C++ 16-18/02/2009 42 / 201
Exercice
Decomposition en nombres premiers
Rappels sur map (liste associative)
1 #i nc l ude <map>
2
3 // de c l a r a t i o n d une l i s t e dont l e s i n d i c e s s ont e n t i e r s ,
4 // et dont l e s a s s o c i a t i o n s s ont e n t i `e r e s
5 s t d : : map<i nt , i nt > map numbers ;
6
7 map numbers . count ( 42) ; // r e t our ne 1 s i 42 e s t dans l a l i s t e des i n d i c e s , 0 s i non
8 map numbers [ 4 2 ] = 73; // met l a v a l e u r 73 `a l i n d i c e 42
9 i n t i = map numbers [ 4 2 ] ; // met l a v a l e u r de l i n d i c e 42 dans i ( s eul ement s i 42 f a i t p a r t i e des i n d i c e s
de map numbers , s i non e r r e u r )
Rappels sur set (ensemble ordonne)
1 #i nc l ude <s et >
2
3 // de c l a r a t i o n d un ensembl e or donne d e n t i e r s
4 s t d : : s et <i nt > pr i me number s ;
5
6 pr i me number s . count ( 42) ; // r e t our ne 1 s i 42 e s t dans l a l i s t e des i n d i c e s , 0 s i non
7 pr i me number s . i n s e r t ( 42) ; // met l a v a l e u r 73 `a l i n d i c e 42
8 pr i me number s . i n s e r t ( 74) ;
9
10 // par c our s de l ensembl e
11 f or ( s t d : : s et <i nt >: : c o n s t i t e r a t o r i t = pr i me number s . begi n ( ) , i t e = pr i me number s . end ( ) ;
12 i t != i t e ;
13 ++i t ) {
14 s t d : : cout << i t << " " ;
15 }
Enciaud (INRIA) C++ 16-18/02/2009 43 / 201
Pointeurs sur membres
Syntaxe
Les pointeurs sur membre non static doivent indiquer quils pointent `a linterieur
dune classe. Il doivent donc specier le bon espace de nom.
1 s t r uc t A {
2 i n t i , j , k , l , m, n ;
3 i n t methode ( f l o a t ) ;
4 i n t methode2 ( f l o a t ) ;
5 };
6 i n t A: : ; // po i nt e ur s ur un e n t i e r de A
7 i n t A: : p i = &A: : i ; // po i nt e ur p i s ur un e n t i e r dans A, i n i t i a l i s e s ur l a dr e s s e de i
8 i n t (A: : ) ( f l o a t ) ; // po i nt e ur s ur une methode de A ( r e t our na nt i nt , et pr enant un argument f l o a t )
9 i n t (A: : p methode ) ( f l o a t ) = &A: : methode2 ; // po i nt e ur p methode i n i t i a l i s e s ur A: : methode2
1
Sils pointent sur un membre static, ils sont absolus, nont pas besoin de
specier lespace de nom, et nont pas besoin dune instance pour etre
deferences.
2
Sils pointent sur un membre non static, ils sont valident naturellement `a
travers une instance (necessaire pour deferencer le pointeur).
Enciaud (INRIA) C++ 16-18/02/2009 44 / 201
Pointeurs sur membres
Syntaxe (2)
1 c l a s s A2 {
2 publ i c :
3 s t a t i c cons t i n t i = 0;
4 const i n t j = 1;
5 f l o a t myOperati on1 ( const A2&) const ;
6 f l o a t myOperati on2 ( const A2&) const ;
7 f l o a t myOperati on3 ( const A2&) const ;
8 s t a t i c f l o a t myOperati on4 ( const A2&) ;
9 s t a t i c f l o a t myOperati on5 ( const A2&) ;
10 s t a t i c i n t i ;
11 i n t j ;
12 };
13 i n t A2 : : i = 0;
14
15 // . . .
16
17 // d e f i n i t i o n du t ype
18 // po i nt e ur s ur une f o n c t i o n membre ( c f r e t o ur () ( ) )
19 // dans l e namespace A ( c f . A: : )
20 // et l a i s s a n t l e namespace i nchange ( cons t f i n a l )
21 // r e t our na nt f l o a t et pr enant un r e f e r e n c e cons t s ur A
22 t ypedef f l o a t ( A2: : o pe r a t o r t y pe ) ( const A2&) const ;
23
24 // de c l a r a t i o n de v a r i a b l e s
25 o pe r a t o r t y pe v1 = &A2 : : myOperati on1 , v2 = &A2 : : myOperati on3 ;
26
27 // po i nt e ur s ur methode s t a t i c , i d e n t i q u e `a un po i nt e ur s ur f o n c t i o n
28 f l o a t (v4 ) ( const A2&) = &A2 : : myOperati on5 ;
Enciaud (INRIA) C++ 16-18/02/2009 45 / 201
Pointeurs sur membres
Syntaxe (3)
1 // a ppe l s
2 A2 a1 ;
3 A2 a2 = &a1 ;
4 ( a1.v1 ) ( a1 ) ;
5 a2>v2 ( a1 ) ; // methode non s t a t i c
6
7 v4 ( a1 ) ; // methode s t a t i c
8
9 i n t A2: : p j = &A2 : : j ;
10 i n t p i = &A2 : : i ;
11 a1. p j = 10; // v a r i a b l e non s t a t i c
12 p i = 20; // v a r i a b l e s t a t i c
Enciaud (INRIA) C++ 16-18/02/2009 46 / 201
Constructeurs
Denition
Denition (Constructeur)
Le constructeur initialise la classe, cest-`a-dire ses ressources et ses variables
membres. Il est represente par la methode portant le nom de la classe. Il peut etre
surcharge.
Denition (liste dinitialisation)
Il sagit dune liste apparaissant juste apr`es la parenth`ese fermante du
constructeur, et commencant par :. Elle se termine avec laccolade ouvrante du
constructeur.
1 s t r uc t A {
2 i n t i , j , k
3 A( ) : // debut de l a l i s t e d i n i t i a l i s a t i o n
4 i ( 0)
5 , j ( 1)
6 , k ( 2)
7 { // f i n de l a l i s t e d i n i t i a l i s a t i o n
8 }
9 };
Enciaud (INRIA) C++ 16-18/02/2009 47 / 201
Constructeurs
Rappel
`
A ne pas confondre...
1 A a ; // de c l a r a t i o n d un o bj e t a de t ype A: l e c o ns t r u c t e ur par de f aut e s t u t i l i s e
2 A a ( ) ; // de c l a r a t i o n d une f o n c t i o n a , s ans par am`et r es et r e t our na nt un o bj e t de t ype A
Enciaud (INRIA) C++ 16-18/02/2009 48 / 201
Constructeurs
Par defaut // par recopie
Denition (Constructeur par defaut)
Constructeur appele sans arguments
Denition (Constructeur par recopie)
Constructeur avec comme argument une reference `a une autre instance de la
meme classe
1 c l a s s A {
2 s t d : : s t r i n g s ;
3 publ i c :
4 A( ) : s ( 0) {} // c o ns t r u c t e ur par de f aut
5 A( const A& a ) : s ( new s t d : : s t r i n g (a . s ) ) {} // c o ns t r u c t e ur par r e c o p i e
6 };
Attention ! !
Si non deni, le compilateur gen`ere *automatiquement* des constructeurs par
defaut (si possible) et/ou par recopie (si possible).
Enciaud (INRIA) C++ 16-18/02/2009 49 / 201
Constructeurs
Construction des variables membres
Les variables membres sont construites dans la liste dinitialisation.
1 s t r uc t A {
2 i n t i , j , k
3 A( ) : // debut de l a l i s t e d i n i t i a l i s a t i o n
4 i ( 0)
5 , j ( 1)
6 , k ( 2)
7 { // f i n de l a l i s t e d i n i t i a l i s a t i o n
8 }
9 };
Ordre de construction
Lordre de construction des variables membres suit lordre de declaration dans la
classe.
Rappel : les methodes ne sont pas des variables (et donc ninuencent pas la taille
de la classe).
Enciaud (INRIA) C++ 16-18/02/2009 50 / 201
Constructeurs
Construction des variables membres (2)
Il existe bien des mani`eres dinitialiser un objet...
Construction par defaut
Si le constructeur dune variable membre nest pas appele explicitement dans la
liste dinitialisation, et si la variable nest pas de type POD, alors son constructeur
par defaut est appele.
1 c l a s s A {
2 s t d : : s t r i n g s ;
3 i n t i , j ;
4 publ i c :
5 A( ) : s ( ) , i ( 0) {}
6 // j , non i n i t i a l i s e ( vaut n i mpor t e quoi ) c ar i n t n a pas de c o n s t r uc t e u r par de f aut
7 };
Il est plus performant dinitialiser les variables membres directement dans la liste
dinitialisation, plutot que dans le corps du constructeur (bonne pratique :
linitialisation nest faite quune fois).
Enciaud (INRIA) C++ 16-18/02/2009 51 / 201
Constructeurs
Contr ole dacc`es
Les memes r`egles dacc`es sappliquent au constructeur :
Denition (constructeur public)
Constructeur appelable par tout le monde
Denition (constructeur prive)
Constructeur appelable uniquement par la classe elle-meme
1 c l a s s A {
2 s t d : : s t r i n g s ;
3 A( const A&) ; // i n t e r d i t l u t i l i s a t i o n i mp l i c i t e du c o n s t r uc t e u r par r e c o p i e
4 publ i c :
5 A( ) : s ( 0) {} // d e f i n i et i mpl ement e l e c o n s t r u c t e ur par de f aut
6 };
Denition (constructeur protege)
Constructeur appelable uniquement par une classe lle (cf. heritage)
Enciaud (INRIA) C++ 16-18/02/2009 52 / 201
Exercice
Copy constructible
Objectif
Faire en sorte que la classe suivante soit copy constructible, cest-`a-dire quelle
implemente le constructeur par recopie.
Classe Test
1 s t r uc t A uni on {
2 uni on {
3 s t d : : s t r i n g s ;
4 const char p ;
5 doubl e d ;
6 } c u r r e n t v a l u e ;
7 enum {
8 e s t r i n g ,
9 e char ,
10 e f l o a t
11 } c u r r e n t t y p e ;
12
13 const i n t s ome i nt ;
14
15 A uni on ( ) : s ome i nt ( 0) , c u r r e n t t y p e (
e f l o a t ) , c u r r e n t v a l u e ( ) {}
16 A uni on ( ) { i f ( c u r r e n t t y p e == e s t r i n g )
del et e c u r r e n t v a l u e . s ; }
17 };
1 A uni on a ;
2 s t d : : cout << a ;
3
4 a . c u r r e n t t y p e = A uni on : : e s t r i n g ;
5 a . c u r r e n t v a l u e . s = new s t d : : s t r i n g ( "this is
a string" ) ;
6 s t d : : cout << a ;
7
8 A uni on b = a ;
9 s t d : : cout << b ;
Enciaud (INRIA) C++ 16-18/02/2009 53 / 201
Exercice
Copy constructible(2)
Objectif
Faire en sorte que la classe suivante soit non copy constructible.
Classe Test
1 s t r uc t A uni on {
2 uni on {
3 s t d : : s t r i n g s ;
4 const char p ;
5 doubl e d ;
6 } c u r r e n t v a l u e ;
7 enum {
8 e s t r i n g ,
9 e char ,
10 e f l o a t
11 } c u r r e n t t y p e ;
12
13 A uni on ( ) : s ome i nt ( 0) , c u r r e n t t y p e (
e f l o a t ) , c u r r e n t v a l u e ( ) {}
14 };
1 A uni on a ;
2 s t d : : cout << a ;
3
4 a . c u r r e n t t y p e = A uni on : : e s t r i n g ;
5 a . c u r r e n t v a l u e . s = new s t d : : s t r i n g ( "this is
a string" ) ;
6 s t d : : cout << a ;
7
8 A uni on b = a ;
9 s t d : : cout << b ;
Enciaud (INRIA) C++ 16-18/02/2009 54 / 201
Constructeurs
Variable membres const
Variables membres const
Ne peuvent etre changee apr`es instanciation de la classe
Donc...
Doivent etre initialisee dans la liste du constructeur
1 c l a s s A {
2 const i n t i , j ;
3 publ i c :
4 A( ) : i ( 0) {
5 j = 1; // e r r e u r
6 }
7 };
Enciaud (INRIA) C++ 16-18/02/2009 55 / 201
Constructeurs
Variable membres reference
Les references doivent etre initialisees dans la liste dinitialisation.
Attention
Les attributs references doivent referer soit :
des objets dont la duree de vie depasse celle de la classe !
soit des objets temporaires automatiques(ce qui veut dire que la reference
est const)
Les variablesreferences etant constantes, elles doivent etre initialisees dans la
liste constructeur egalement.
Trouver le bug
1 s t r uc t A {
2 s t d : : s t r i n g &s
3 A( s t d : : s t r i n g s ) : s ( s ) {}
4 };
5
6 A a ( "value__" ) ;
7 i f ( a . s == "value__" )
8 s t d : : cout << "compilo bugg e !" << s t d : : e ndl ;
Ce code fonctionne sous GCC 4.0.1 MacOSX et non sous Visual Studio 2008... mais ca reste un bug, meme sil fonctionne sur certaines architectures
Enciaud (INRIA) C++ 16-18/02/2009 56 / 201
Constructeurs
Restriction des conversions : mot clef explicit
Denition (explicit)
Force lappel du constructeur avec les types exacts passes en param`etres de
celui-ci.
Aucun trans-typage(conversion implicite) nest eectue pour les constructeurs
explicites.
1 s t r uc t A {
2 e x p l i c i t A( i nt , const f l o a t &) ;
3 e x p l i c i t A( l ong , const doubl e&) ;
4 };
Enciaud (INRIA) C++ 16-18/02/2009 57 / 201
Constructeurs
Mise en garde
Limite sur lutilisation de this
La classe est totalement construite `a la n du bloc du constructeur (heritage de
classe).
Donc ...
On ne peut pas utiliser this correctement
Mais ...
Les variables membres existent `a lentree du bloc du constructeur
Enciaud (INRIA) C++ 16-18/02/2009 58 / 201
Destructeurs
Presentation
Objet
1
Detruit les objets qui appartiennent `a la classe
2
Lib`ere la memoire allouee par la classe
3
G`ere la duree de vie des pointeurs.
Il porte le meme nom que la classe, et na jamais de param`etres en entree. Il faut
lappeler avec loperateur deleteet (pratiquement) jamais directement.
Syntaxe
1 s t r uc t A {
2 A( ) {}
3 };
Dans un programme stable, le destructeur est TOUT AUSSI important que le
constructeur (ou nimporte quelle autre methode).
Les objets sont detruits dans lordre inverse de leur declaration lors de laccolade
fermante du destructeur.
Enciaud (INRIA) C++ 16-18/02/2009 59 / 201
Exercice
Classe de matrice
Enonce
Ecrire une classe de matrice matrice dde type double. Le constructeur de la
classe aura pour param`etres deux entiers indiquant la taille (allocation dynamique).
Enciaud (INRIA) C++ 16-18/02/2009 61 / 201
Classes & surcharge doperateurs
Introduction
Denition (operateurs)
Fonctions unaires ou binaires
Lorsquon deni loperateur dune classe, on dit generalement quon surcharge cet
operateur. Ce sous-entend que si ces operateurs ne sont pas denis, le compilateur
essaie de les generer automatiquement.
Plusieurs operateur dinteret, exemple :
1 oper at or= ; // a t t r i b u t i o n
2 oper at or== ; oper at or != ; oper at or <; oper at or > ; . . . // compar ai s on
3 oper at or++ ; oper at or ; // auto i nc r e me nt a t i on et dec r e me nt at i on ( pre ou pos t )
4 oper at or+ ; oper at or +=; oper at or ; oper at or =; . . . // a r i t hme t i que
5 oper at or ; // def er encement ou mu l t i p l i c a t i o n
6 oper at or ! ; // ne gat i on
Enciaud (INRIA) C++ 16-18/02/2009 62 / 201
Classes & surcharge doperateurs
Types doperateurs
Il existe deux types doperateurs :
1
les operateurs unaires : ils nimpliquent quun seul objet, et donc ne prennent
pas de param`etres
1 s t r uc t A {
2 A oper at or ! ( ) ;
3 };
2
les operateurs binaires : ils impliquent deux objets : lobjet courant, implicite
et `a gauche de lexpression, et lobjet argument (explicite, en param`etre)
1 s t r uc t U {};
2 s t r uc t A {
3 A oper at or +( const U&) ;
4 };
5 A a , b ;
6 U u ;
7 b = a + u ; // a ( de t ype A) e s t `a gauche de u ( de t ype U)
Si lon souhaite denir un operateur alors que loperande gauche est dun autre
type, il faut faire appel aux methodes amies.
Dans une expression, le sens de levaluation depend de la priorite de loperateur.
Enciaud (INRIA) C++ 16-18/02/2009 63 / 201
Exercice
Operateurs arithmetiques
Enonce
Pour une matrice :
Ecrire les operateurs daddition, de multiplication avec un double
Ecrire loperateur de multiplication avec une autre matrice
Enonce
Ecrire loperateur daddition entre deux decompositions en nombre premier
(classe decomposed primes).
Ecrire loperateur daddition entre une decomposition et un entier
Ecrire loperateur de multiplication (deux decomposed primeset un entier)
Ecrire loperateur de division (deux decomposed primeset un entier) : on se
permet davoir des exposants negatifs
Enciaud (INRIA) C++ 16-18/02/2009 64 / 201
Operateur dattribution
Denition & syntaxe
Denition (operator=)
Operateur permettant de changer letat de la classe grace au signe =.
Syntaxe
1 s t r uc t A {
2 A& oper at or =( const A&) ;
3 };
Cet operateur est utile lorsque la copie nest pas triviale (ie. typiquement avec
membres de type pointeurs et/ou references). Souvent, lorsque loperateur ne peut
etre genere automatiquement, le compilateur emet un avertissement (warning).
Enciaud (INRIA) C++ 16-18/02/2009 65 / 201
Operateur dattribution
Transitivite
Transitivite : a = b = c = . . . = z
= est transitif
Il doit etre possible decrire :
1 s t r uc t A {/ . . . /} a1 , a2 , a3 ;
2 a1 . i n i t ( 42) ; // i n i t i a l i s a t i o n
3 a2 = a3 = a1 ; // t r a n s i t i v i t e
Donc
Le retour de loperateur dattribution doit etre une reference sur linstance.
Exemple :
1 A& A: : oper at or =( const A& r ) {
2 i = r . i ;
3 r et ur n t h i s ;
4 }
Enciaud (INRIA) C++ 16-18/02/2009 66 / 201
Operateur dattribution
Remarque : auto-attribution (1)
Il faut gerer le cas a = a
Cest-`a-dire ... il doit etre possible decrire :
1 s t r uc t A { s t d : : s t r i n g s ; A& A: : oper at or =( const A& r ) ; } a ;
2 a = a ; // autoa t t r i b u t i o n
sans danger pour la classe a ;
Exemple `a ne pas faire...
1 A& A: : oper at or =( const A& r ) {
2 del et e s ;
3 s = new s t d : : s t r i n g ( r . s ) ; // s n e x i s t e pl us s i &r == t h i s
4 r et ur n t h i s ;
5 }
Enciaud (INRIA) C++ 16-18/02/2009 67 / 201
Operateur dattribution : remarques
Auto-attribution (2)
Donc...
1
gerer explicitement le cas a = a par this
1 A& A: : oper at or =( const A& r )
2 {
3 i f ( t h i s == &r ) r et ur n t h i s ;
4 del et e s ;
5 s = new s t d : : s t r i n g ( r . s ) ;
6 r et ur n t h i s ;
7 }
2
changer lordre des operations pour avoir une gestion implicite
1 A& A: : oper at or =( const A& r )
2 {
3 s t d : : s t r i n g s tmp = new s t d : : s t r i n g ( r . s ) ;
4 del et e s ;
5 s = s tmp ;
6 r et ur n t h i s ;
7 }
Enciaud (INRIA) C++ 16-18/02/2009 68 / 201
Operateur dattribution
Code auto-genere
Le compilateur saitfaire des choses :
Si les types contenus dans la structure/classe sont de type triviaux ou poss`edent
tous un constructeur par recopie (deni ou trivial), alors il nest pas necessaire de
denir loperateur dattribution (meme remarque sapplique au constructeur par
recopie).
Donc :
Necrire loperateur dattribution seulement quand vous le jugez necessaire
(membres pointeur/reference/const).
Enciaud (INRIA) C++ 16-18/02/2009 69 / 201
Operateur dattribution
Classe de matrice
Enonce
Ecrire loperateur dattribution de la matrice avec une autre matrice : si les
matrices ne sont pas de meme taille, alors on fait la recopie.
Ecrire loperateur dattribution entre une matrice et une autre, entre une
matrice et un entier.
Enciaud (INRIA) C++ 16-18/02/2009 70 / 201
Operateur de conversion
Denition
Denition (operator T)
Operateur appele lors dun cast explicite vers un type particulier.
Cet operateur peut etre tr`es pratique dans certains cas. Il ne denit pas de type de
retour, puisque ce type est implicite par le cast.
Syntaxe
1 s t r uc t A { oper at or i n t ( ) { / c a s t de A v e r s e n t i e r i n t / } };
Exercice
Ecrire une classe qui ache des informations sur son etat lorsquon la transforme
en chane de caract`ere. On utilisera par exemple la classe decomposed primeset
la classe matrice d(exercices precedents - pour decompose primesvoir la
fonction fournie dans les chiers).
Enciaud (INRIA) C++ 16-18/02/2009 71 / 201
Classes : surcharge doperateur
Operateur de fonction
Denition (operator())
Operateur donnant `a la classe linterface dune fonction.
Syntaxe
1 s t r uc t A {
2 bool oper at or ( ) ( doubl e , f l oa t , i n t ) const ;
3 f l o a t oper at or ( ) ( i nt , f l o a t ) ;
4 };
5
6 A a ;
7 a ( 0. 34 , . 32 f , 42) ;
8 a ( 42 , . 32 f ) ;
Exercice
Ecrire loperateur de fonction de la matrice, an dacceder `a ses elements.
Question subsidiaire : pourquoi ne pas utiliser loperator [] ?
Enciaud (INRIA) C++ 16-18/02/2009 72 / 201
Heritage
Introduction
Controle dacc`es
Visibilite & desambigusation
Construction et destruction
Conversions
Heritage multiple
Classes virtuelles
Classes virtuelles pures
Interfaces
Enciaud (INRIA) C++ 16-18/02/2009 73 / 201
Heritage
Denition
Que signie heritage ?
Soit une classe A heritant dune classe B :
1
A herite partiellement du comportement de B
2
A herite(semantiquement parlant) de B par le biais des methodes de B
3
A herite egalement des attributs de B, sils sont marques comme tel,
cest-`a-dire si les attributs de B ont un acc`es public ou protege.
4
A herite des champs de type de B
Syntaxe :
1 c l a s s B {};
2 c l a s s A : [ ac c`e s ] B {}; // ac c`e s : publ i c , pr ot e c t e d ou p r i v a t e ( ou r i e n )
Enciaud (INRIA) C++ 16-18/02/2009 74 / 201
Heritage
Contr ole dacc`es
Le controle dacc`es dune classe m`ere sapplique aux classes lles. Lacc`es `a la
classe m`ere peut etre davantage restreint.
1 c l a s s B {
2 s t d : : s t r i n g s ; // a t t r i b u t p r i v e
3 pr ot ect ed :
4 i n t v al ue ; // a t t r i b u t a c c e s s i b l e aux c l a s s e s he r i t a n t de B
5 publ i c :
6 i n t p u b l i c v a l u e ;
7 voi d pr i nt Me ( ) const ;
8 };
9
10 c l a s s A : publ i c B {
11 // A ne peut ac ce de r `a s mai s peut ac ce de r `a v al ue et p u b l i c v a l u e
12 // v al ue e s t pr ot e c t e d
13 // p u b l i c v a l u e e s t p u b l i c
14 };
15
16 A a ;
17 a . v al ue = 10; // e r r e ur , v al ue e s t pr ot e c t e d
18 a . pr i nt Me ( ) ; // a he r i t e de ce comportement , c ar l he r i t a g e de B e s t p u b l i c
Enciaud (INRIA) C++ 16-18/02/2009 75 / 201
Heritage
Contr ole dacc`es (2)
Si lacc`es nest pas specie, par defaut il est :
private pour les classes
public pour les structures
Heritage de type
public : visibilite inchangee (acc`es aux membres public et protected)
private : la totalite des membres accessibles (ie. non prives) de la classe m`ere
deviennent prives
protected : public devient protected (private toujours inaccessible)
Enciaud (INRIA) C++ 16-18/02/2009 76 / 201
Heritage
Visibilite
Les attributs de la classe courante sont visibles prioritairement sur celles de la
classe m`ere.
Les methodes peuvent donc boucler sur elle-meme !
Denitions Usage
1 s t r uc t A {
2 t ypedef i n t v a l ue t y pe ;
3 v a l ue t y pe doSthg ( ) const ;
4 };
5
6 s t r uc t B : publ i c A {
7 t ypedef f l o a t v a l ue t y pe ;
8 t ypedef A: : v a l ue t y pe a v a l u e t y p e ;
9 v a l ue t y pe doSthg ( ) const {
10 doSthg ( ) ; // a p p e l l e B: : doSthg au l i e u de
A: : doSthg
11 // do some ot he r t hi ng s
12 }
13 };
1 B b ;
2 B: : v a l ue t y pe v a l = b . doSthg ( ) ; // v a l e s t
f l o a t , bouc l e i n f i n i me n t
Il est possible de se referer explicitement `a une methode ou un attribut de lune
des classes m`eres (si les controles dacc`es le permettent), par la syntaxe suivante :
1 B: : v a l ue t y pe doSthg ( ) const {
2 A: : doSthg ( ) ; // a p p e l l e A: : doSthg au l i e u de A: : doSthg
3 // do some ot he r t hi ng s
4 }
Enciaud (INRIA) C++ 16-18/02/2009 77 / 201
Heritage
Constructeurs
Une classe lle contient la classe m`ere (cen est une extension). Donc, si la classe
lle est construite, il faut que la classe m`ere le soit egalement.
Constructeur : r`egle
Le constructeur par defaut de la classe m`ere est appele avant linitialisation
du premier (ie. de tous) membre de la classe lle.
La classe lle peut appeler un constructeur particulier de la classe m`ere, dans
sa liste dinitialisation
En fait, la classe m`ere peut etre vue (en terme dimplementation) comme une
variable membre avant toutes les autres.
Les controles dacc`es du constructeur de la classe m`ere est identique `a nimporte
quelle autre membre
Enciaud (INRIA) C++ 16-18/02/2009 78 / 201
Heritage
Constructeurs : exercice
Soit la classe m`ere suivante, ouvrant un chier dans le repertoire courant :
1 c l a s s F i l e Ut i l {
2 publ i c :
3 // i n i t i a l i s e l a c l a s s e avec l e f i c h i e r non ouv e r t f i l e na me
4 F i l e Ut i l ( const s t d : : s t r i n g &f i l e na me ) {/ . . . /}
5
6 / . . . /
7 };
Une fois le chier ouvert, la classe propose des manipulations de ce chier (or de
propos ici).
Nous souhaitons une nouvelle classe heritant ces methodes de manipulation, mais
ouvrant les chiers de mani`ere dierente.
Note : Nous considererons que la classe m`ere stocke un handle de chier dans la
variable membre FILE m le handler . Elle orirait `a ses classes lles un
constructeur particulier...
Enciaud (INRIA) C++ 16-18/02/2009 79 / 201
Heritage
Destructeurs
Destructeur : r`egle
Le destructeur de la classe m`ere est appele apr`es la destruction de tous les membre
de la classe lle (lors de lexecution de laccolade fermante de la classe lle).
Cest `a dire, dans lordre inverse de la creation des elements.
Enciaud (INRIA) C++ 16-18/02/2009 80 / 201
Heritage
Conversions
Il est possible de couper une classe, mais il nest pas possible dinventer des
extensions de classe.
Une classe lle est une extension de sa classe m`ere. Il est donc possible de
presenter la partie concernant sa classe m`ere.
1 // A f i l l e de B
2 A a ;
3 B p b = &a ; // du pl us p r e c i s au pl us ge ne r a l
4 B& r e f b = a ;
Linverse nest pas vrai, car il faudrait inventer des donnees manquantes :
1 // B f i l l e de A
2 A a ;
3 B p b = &a ; // e r r e u r de c ompi l a t i on : l e c ompi l at e ur ne s a i t pas
4 B& r e f b = a ; // s i ces i n s t r u c t i o n s s ont v a l i d e s ( a p r i o r i e l l e s ne l e s ont pas ) .
Enciaud (INRIA) C++ 16-18/02/2009 81 / 201
Heritage
Conversions & dynamic cast
Denition (dynamic cast)
Operateur permettant de determiner si une classe est transformable (cast) en
une autre en suivant le graphe de lheritage de classe. Dans le cas de pointeurs en
argument de loperateur, si le cast echoue, loperateur renvoie 0(zero).
1 s t r uc t A {};
2 s t r uc t B : publ i c A {};
3 B b ;
4 A p b = &b ;
5 B p b2 = dynami c cast <B>(p b ) ;
Il est possible de tester `a lexecution(et parfois `a la compilation), `a partir dun
pointeur ou dune reference sur une classe, si une classe derive ou est une classe
m`ere dune autre.
Plus precisement, le compilateur sait si une classe est m`ere dune autre `a la
compilation, mais linverse nest pas vrai. Le test doit etre fait en runtime.
Enciaud (INRIA) C++ 16-18/02/2009 82 / 201
Heritage multiple
Denition
Denition (Heritage multiple)
Lheritage multiple est lorsquune classe herite de plusieurs autres classes.
1 s t r uc t A {};
2 s t r uc t B {};
3 s t r uc t C : publ i c A, publ i c B {}; // he r i t e de A et B
Les memes r`egles que lheritage simple sappliquent pour :
Les controles dacc`es
La visibilite
Le graphe dheritage etant plus complexe, le compilateur peut se plaindre parfois
de ne pas pouvoir resoudre un appel (deux classes m`eres ayant une methode de
meme nom/param`etres). Il faut alors faire la desambigusation de la meme
mani`ere que pour lheritage simple.
Enciaud (INRIA) C++ 16-18/02/2009 83 / 201
Heritage multiple
Constructeurs & destructeurs
De la meme mani`ere que pour lheritage simple :
Les classes m`eres sont toutes construites avant nimporte quel attribut
membre de la classe.
Si aucun constructeur de classe m`ere nest appele dans la liste dinitialisation,
le constructeur par defaut est appele.
Les classes m`eres sont construites de gauche `a droite dans la liste des classes
de base (ex. precedent : A puis B).
et
Les classes m`eres sont detruites apr`es destruction du dernier membre de la
classe lle
Elles sont detruites dans lordre inverse de leur construction (de droite `a
gauche dans la liste des classes de base).
Enciaud (INRIA) C++ 16-18/02/2009 84 / 201
Classes virtuelles
Denition
Classe virtuelle - Denition
Une classe virtuelle est classe contenant au moins une methode virtuelle
Methode virtuelle - Denition
Methode dont limplementation peut etre (re)denie par une classe derivee.
Le mot clef virtual indique si la methode en question est virtuelle (ou pas).
Une methode virtuelle participe `a la taille occupee en memoire par la classe.
Methode virtuelle
La methode appelee par defaut (ie. sans specication despace de nom) est
toujours la plus profonde dans la hierarchie des classes.
Enciaud (INRIA) C++ 16-18/02/2009 85 / 201
Classe virtuelle
Exemple
Classes virtuelles
Classe A (m`ere) Classe implementation A (lle) - invisible
1 c l a s s A {
2 s t d : : s t r i n g s ;
3 publ i c :
4 A( const s t d : : s t r i n g &s = "" ) : s ( s ) {}
5 A( ) {}
6 v i r t u a l voi d pr i nt Me ( ) const {
7 s t d : : cout << "I am A" << s t d : : e ndl ;
8 }
9 };
1 // c l a s s e d i mpl ement at i on
2 c l a s s A i mpl : publ i c c l a s s A {
3 i n t p ;
4 publ i c :
5 A i mpl ( const i n t s i z e = 1000000000000) : A
( ) , p ( 0) {
6 p = new i n t [ s i z e ] ; }
7 A i mpl ( ) { del et e [ ] p ; }
8
9 v i r t u a l voi d pr i nt Me ( ) const {
10 s t d : : cout << "I am the implementation of
A" << s t d : : e ndl ;
11 }};
12 // f a c t o r y
13 A f ac t or yA ( ) { r et ur n new A i mpl ( ) ; }
Appel
1 A my c l as s = f ac t or yA ( ) ;
2 my cl as s>pr i nt Me ( ) ;
Enciaud (INRIA) C++ 16-18/02/2009 86 / 201
Classes virtuelles
Utilisation
Ranement/specialisation du comportement dune classe
Classe m`ere fournit des services minimaux
Utilisation dalgorithmes existants avec de nouvelles implementations
Classe implementation A (lle)
1 c l a s s A i mpl : publ i c c l a s s A {
2 i n t p ;
3 publ i c :
4 A i mpl ( const i n t s i z e = 1000000000000) : A( ) , p ( 0) { p( new i n t [ s i z e ] ) ; }
5 A i mpl ( ) { del et e [ ] p ; }
6
7 v i r t u a l voi d pr i nt Me ( ) const {
8 A: : pr i nt Me ( ) ;
9 s t d : : cout << "I am the implementation of A" << s t d : : e ndl ;
10 s t d : : cout << "I print some additional information" << s t d : : e ndl ;
11 }
12 };
Enciaud (INRIA) C++ 16-18/02/2009 87 / 201
Classes virtuelles pures
Denition
Denition (Classe virtuelle pure)
Une classe virtuelle pure est classe contenant au moins une methode virtuelle pure.
Denition (Methode virtuelle pure)
Methode virtuelle sans implementation (ie. = 0)
Syntaxe
1 s t r uc t A {
2 // Methode v i r t u e l l e pur e
3 v i r t u a l voi d pr i nt Me ( ) const = 0;
4 };
Enciaud (INRIA) C++ 16-18/02/2009 88 / 201
Classes virtuelles pures
Proprietes
Une classe virtuelle pure ne peut etre instanciee
1 s t r uc t A {
2 v i r t u a l voi d pr i nt Me ( ) const = 0;
3 };
4 A a = new A( ) ; // e r r e u r `a l a c ompi l a t i on : pr i nt Me non d e f i n i t
Une classe m`ere peut donc forcerlimplementation (dans les classes lles) des
methodes quelle declare pures
Enciaud (INRIA) C++ 16-18/02/2009 89 / 201
Destructeurs
Heritage
Que se passe-t-il si delete est appele `a partir dune la classe m`ere ?
Exemple
Classe m`ere : interface Classe lle et factory: implementation reelle
1 s t r uc t A {
2 s t d : : s t r i n g s ;
3 A( const s t d : : s t r i n g &s ) : s ( s ) {}
4 A( ) {}
5 v i r t u a l voi d doSomethi ng ( ) = 0;
6 };
1 s t r uc t A i mpl : publ i c s t r uc t A {
2 A i mpl ( const i n t s i z e = 1E5) : A( ) , p ( 0) {
p( new i n t [ s i z e ] ) ; }
3 A i mpl ( ) { del et e [ ] p ; }
4 v i r t u a l voi d doSomethi ng ( ) {}
5
6 pr i v a t e : i n t p ;
7 };
8
9
10 A f ac t or yA ( ) {
11 r et ur n new A i mpl ( ) ;
12 }
1 A my c l as s = f ac t or yA ( ) ;
2 del et e my c l as s ;
Faire lessai, et proposer une solution.
Enciaud (INRIA) C++ 16-18/02/2009 91 / 201
Interfaces
Denition
Denition (Interface)
Sert `a denir un couplageentre un service (lobjet/composant) et ses clients.
Concept general indiquant les methodes pour acceder `a un objet (au moins en
exploiter certaines fonctionnalites) : linterface denie la signature pour
lutilisation de ces fonctionnalites. La particularite importante de linterface est le
decouplage de lacc`es dun objet et de son implementation. Cette particularite fait
en sorte que :
1
Les clients ne connaissent pas les details dimplementation, et ne sont donc
pas soumis aux variations de celle-ci (concept objet).
2
Linterface est supposee stable en termes de fonctionnalites et signatures,
notamment par rapport `a levolution dun composant logiciel.
3
Lapproche par interfaces est souvent moins performante, puisque les
signatures ne sont pas optimales pour une implementation particuli`ere (et que
lacc`es aux variables membres se fait par le biais de methodes dacc`es).
En C++, une interface est une classe ne denissant aucune variable membre et
dont toutes les methodes sont publiques et virtuelles pures.
Enciaud (INRIA) C++ 16-18/02/2009 92 / 201
Interfaces
Exemple
Interface dune objet permettant dexploiter des videos
1 c l a s s I Vi d e o Se r v i c e {
2 publ i c :
3 v i r t u a l bool openVi deo ( const s t d : : s t r i n g& f i l e na me ) = 0;
4 v i r t u a l bool i sOpen ( ) const = 0;
5 v i r t u a l bool c l os e Vi de o ( ) = 0;
6
7 v i r t u a l bool seekFrame ( l ong i n t f rame number ) = 0;
8 v i r t u a l i n t getFrame ( unsi gned char buf f e r , const l ong i n t b u f f e r s i z e , i n t &wi dth , i n t &he i ght ) = 0;
9
10
11 // De s t r uc t e ur v i r t u e l
12 v i r t u a l I Vi d e o Se r v i c e ( ) {}
13 };
Rappel
Ne jamais oublier le destructeur virtuel
Meme sil sagit dun artefact du langage...
Enciaud (INRIA) C++ 16-18/02/2009 93 / 201
Exceptions
structurees
Denition & utilisation
Details
Exceptions & constructeurs
Exceptions & destructeurs
Exceptions standards
Enciaud (INRIA) C++ 16-18/02/2009 94 / 201
Exceptions structurees
Denition
Denition (exception)
Une exception est un mecanisme special du C++, lance par le mot clef throw, et
permettant darreter lexecution courante du programme jusqu`a une instruction
de recuperation dexception (bloc try/ catch).
Linstruction throwpeut etre suivie de nimporte quelle classe, structure, entier.
Linstruction catchintercepte la meme classe que celle du throw.
Syntaxe
Declarations Fonctions levant des exceptions
1 c l a s s Except i on1 {};
2 c l a s s Except i on2 : publ i c Except i on1 {};
3 s t r uc t Except i on3 {
4 const char const what ;
5 Except i on3 ( const char w) : what (w) {}
6 };
1 // f o n c t i o n s
2 voi d f unc t i on1 ( ) {
3 s t d : : cout << "function1 will throw soon" <<
s t d : : e ndl ;
4 throw Except i on1 ( ) ;
5 }
6 voi d f unc t i on2 ( ) {
7 throw f l o a t ( 0. 34 f ) ;
8 }
Enciaud (INRIA) C++ 16-18/02/2009 95 / 201
Exceptions structurees
Interceptions & relancement
Dans le bloc catch, throw sans argument relance lexception au bloc try/catch
superieur.
try/catch
Interceptions Relancement
1 t r y {
2 f unc t i on1 ( ) ;
3 }
4 catch ( Except i on1 &e ) {
5 s t d : : cout << "Caught Ex1" << s t d : : e ndl ;
6 }
7
8 t r y {
9 f unc t i on2 ( ) ;
10 }
11 catch ( f l o a t &e ) {
12 s t d : : cout << "Caught float Ex " << e << s t d
: : e ndl ;
13 }
1 voi d f unc t i on3 ( ) {
2 t r y {
3 f unc t i on1 ( ) ;
4 }
5 catch ( Except i on1& e ) {
6 s t d : : cout << "Caught in f3: rethrow" <<
s t d : : e ndl ;
7 throw ;
8 }
9 }
10
11 t r y {
12 f unc t i o n3 ( ) ;
13 }
14 catch ( Except i on1 &e ) {
15 s t d : : cout << "Caught Ex1 " << s t d : : e ndl ;
16 }
Enciaud (INRIA) C++ 16-18/02/2009 96 / 201
Exceptions structurees
Interception generale
Dans le bloc catch, avec pour argument lellipse ( ... ) interceptes toute les
exceptions.
Attention : puisque lexception nest pas nommee, il nest pas possible davoir plus
de precision sur lexception.
1 t r y {
2 f unc t i on3 ( ) ;
3 }
4 catch ( . . . ) {
5 s t d : : cout << "Caught some unknown exception " << s t d : : e ndl ;
6 }
Mais : Il est possible de relancer lexception
Enciaud (INRIA) C++ 16-18/02/2009 97 / 201
Exceptions structurees
Deroulement des interceptions
Les intructions catchsont testees dans lordre.
1 t r y {
2 f unc t i on3 ( ) ;
3 }
4 catch ( Except i on3 &e ) {
5 s t d : : cout << "Caught Ex3" << s t d : : e ndl ;
6 }
7 catch ( Except i on1 &e ) {
8 s t d : : cout << "Caught Ex1" << s t d : : e ndl ;
9 }
Attention :
1
`a la gestion de lheritage entre plusieurs exceptions
2
`a lellipse, qui masque toute les autres interceptions
Enciaud (INRIA) C++ 16-18/02/2009 98 / 201
Exceptions structurees
Deroulement des interceptions : details
Voici ce quil se passe lorsquune exception est levee :
1
On arrete lexecution du programme au point du throw
2
Le programme teste sil se trouve dans un bloc try(si ce nest pas le cas,
n de programme)
3
On cherche un bloc catchcompatible avec le type de lexception levee (si
aucun, n de programme)
4
On cree une sorte de tunnel/point de connexionavec ce bloc catch, et on
se place dans un mode privilegie
5
Dans ce tunnel, on appelle les destructeurs de tous les objets crees sur la pile,
dans lordre inverse de leur creation
6
On retrouve lexecution du programme au niveau du bloc catch
On appelle le processus de destruction des objets temporaires : le deroulement de
pile (stack unwinding).
Enciaud (INRIA) C++ 16-18/02/2009 99 / 201
Exceptions
Utilisation
Deux philosophies
1
Retour de fonction (comme en Java)
2
Arret dexecution sur faute grave. Exemple : on appelle une fonction denie
par certains crit`eres sur les donnees quelle traite, et ces crit`eres ne sont pas
respectes.
Performances
Plus dinformation sur la pile pour la gestion de lexception, donc ralentissement
des appels.
1
Possibilite de marquer le type dexception possible levee dans une fonction
2
Rapprochement du catch de l`a o` u lexception est potentiellement levee
3
Utilisation dun mot clef pour indiquer quun appel ne l`eve pas dexception ou
ne l`eve une exception que dun certain type (non supporte par tous les
compilateurs).
1 voi d f unc t i on1 ( ) throw ( ) ;
2 voi d f unc t i on2 ( ) throw( Except i on3 ) ;
3 voi d f unc t i on2 ( ) throw ( . . . ) ;
Enciaud (INRIA) C++ 16-18/02/2009 100 / 201
Exceptions
Cohabitation avec les constructeurs
Les exceptions cohabitent tr`es bien avec les constructeurs !
En eet, les constructeurs nont pas de valeur de retour (resultat = objet
construit). Lever une exception dans le constructeur en cas de probl`eme permet :
1
Lorsquune exception est levee dans le constructeur, la classe nest pas creee.
2
Les destructeurs des variables membres initialises sont appeles
3
Le destructeur de la classe en cours de construction nest pas appele (la
classe na pas ete construite).
4
Les destructeurs des classes m`eres instanciees sont appelees (lordre
dinstanciation joue un role important).
Enciaud (INRIA) C++ 16-18/02/2009 101 / 201
Exceptions
Cohabitation avec les destructeurs
Rappel : (quelques diapositives precedentes) le processus de stack unwinding est
execute dans un mode particulier.
En fait, ce mode est particuli`erement fragile, et ne supporte absolument pas un
lancement dexception.
Donc ...
Il NE FAUT PAS lever une exception dans le destructeur
Quavons-nous avec lexemple ci-dessous ?
1 c l a s s A {
2 A( ) {
3 // e x c e pt i on l e ve e dans l e d e s t r u c t e u r de A.
4 throw s t d : : r unt i me e x c e pt i on ( "some error" ) ;
5 }
6 };
7 t r y {
8 A a ;
9 throw s t d : : r unt i me e x c e pt i on ( "juste pour embeter" ) ;
10 } catch ( . . . ) {
11 s t d : : cout << "Cest bon , je recupere" << s t d : : e ndl ;
12 }
Enciaud (INRIA) C++ 16-18/02/2009 102 / 201
Exceptions
Standard STL
Le standard (chier <stdexcept>de la STL) deni quelques exceptions type.
La classe de base est std :: exception, qui implemente la methode
virtual const char std :: exception :: what() const, donnant des
renseignements utilisateurssur le message de lexception.
1 s t d : : r u n t i me e r r o r ; // r e p o r t e l e s e r r e u r s `a l e xe c ut i on
2 s t d : : l o g i c e r r o r ; // r e p o r t e l e s e r r e u r s de l o g i que d appe l
3 s t d : : i nv a l i d a r g ume nt ; // argument i n v a l i d e d un appe l
4 s t d : : out or r a nge ; // r e p o r t e l e s depas s ement s : u t i l i s e dans c e r t a i n s a ppe l s STL ( s ubs t r i ng , v e c t or
. . . )
5 s t d : : b a d a l l o c ; // r e po r t e l e s pr obl `emes d a l l o c a t i o n memoi re ( dans header <new>)
Il faut generalement se reporter `a la documentation pour connatre les exceptions
quon doit recuperer. Les exceptions font partie du comportement du service
demande : elles aectent le fonctionnement de VOTRE programme.
Enciaud (INRIA) C++ 16-18/02/2009 103 / 201
Exceptions
Exercice
But
Soit une classe ContenuFichierqui contient le contenu dun chier.
`
A son
instanciation, il ouvre le chier, lit son contenu et le met dans un buer, puis
ferme le chier.
Il ouvre le chier `a laide de la fonction fopen.
Si le chier nexiste pas, il lance une exception le not found . Cette
exception est `a denir. Elle doit contenir le nom du chier recherche.
Si le chier existe, le constructeur alloue une zone memoire de type char
dune taille de 1024 octet (1Ko). Il lit ensuite le contenu du chier `a laide de
la fonction C fread(#include <cstdio>).
tant quil na pas termine la lecture du chier, il place le bloc precedemment
lu `a la n dun tableau. Pour cela, on utilisera un vecteur STL std :: vector
(#include <vector>) et sa methode std :: vector :: push back.
`a la n de lecture, il doit allouer un gros bloc memoire, dans lequel il va
copier les blocs precedemment lus et places en memoire.
Enciaud (INRIA) C++ 16-18/02/2009 104 / 201
Exceptions
Exercice (suite)
Il doit gerer tr`es proprement
les probl`emes de lecture
les probl`emes dallocation memoire (std :: bad alloc)
la fermeture du chier (toujours)
la liberation des ressources memoires intermediaires
le lancement dexceptions susamment informatives
Enciaud (INRIA) C++ 16-18/02/2009 105 / 201
Etude de cas
Enciaud (INRIA) C++ 16-18/02/2009 106 / 201
Etude de cas
Chane algorithmique
On veut un programme qui applique des algorithmes `a la chane `a une structure
de donnee initiale. Chaque algorithme `a une interface identique `a tous les autres
algorithmes. Il sera identie dans la chane par son nom. Pour chaque chane
algorithmique, chaque algorithme `a un nom unique. Chaque algorithme Apeut
creer une nouvelle donnee, qui pourra etre utilisee dans la chane par les
algorithmes en aval de A. La donnee sera par exemple identiee par son type
exact et le nom de lalgorithme qui la cree.
Lexercice est en deux phases :
1
Phase de reexion/etude/design : `a laide de mecanismes dheritage et
dinterfaces, denissez les intervenants informatiques. On fera un point sur le
design.
2
Phase de developpement : vous retroussez vos manches.
En 4 equipes.
1
Denition de linterface dun algorithme
2
Denition de la structure de donnee
3
Creation de deux algorithmes
Enciaud (INRIA) C++ 16-18/02/2009 107 / 201
Formation C++ avancee
J2 : Programmation generique
Enciaud (INRIA) C++ 16-18/02/2009 108 / 201
J2 : Programmation generique
Contenu
7
Les templates
8
STL
9
Patrons de conception (Design patterns)
Enciaud (INRIA) C++ 16-18/02/2009 109 / 201
Les templates
Introduction
Presentation
Mecanismes
Declaration & denition
Espace de nom
Inference de type
Specialisation
Programmation incrementale
Synth`ese
Enciaud (INRIA) C++ 16-18/02/2009 110 / 201
Template
Introduction : probl`eme de redondance algorithmique
Labelisation
Mesures du nombre
de composantes

Developpements
trop speciques `a
une application !
Sans meta-programmation
Mesures du nombre
de composantes
Mesures de surface
des composantes

Enciaud (INRIA) C++ 16-18/02/2009 111 / 201
Template
Introduction : probl`eme de redondance algorithmique
Labelisation
Mesures du nombre
de composantes

Developpements
trop speciques `a
une application !
Sans meta-programmation
Mesures du nombre
de composantes
Mesures de surface
des composantes

Enciaud (INRIA) C++ 16-18/02/2009 111 / 201
Template
Introduction : probl`eme de redondance algorithmique
Avec meta-programmation
Mesures du nombre
de composantes
Mesures de surface
des composantes
Mta-programme
Enciaud (INRIA) C++ 16-18/02/2009 112 / 201
Templates
Egalement appeles patrons
Denition (Template)
Les templates permettent de denir des familles de classes, structures ou fonctions.
Mecanisme tr`es puissant !
1
permet de rapidement (`a partir dun code compl`etement type) denir une
famille de classe ou de fonction
2
permet dajouter des mecanismes logiques dans le choix des
structures/fonctions invoquees (meta-programmation)
3
permet davoir un code facilement extensible `a des nouveaux cas dutilisation
Dicile `a prendre en main
Certains compilateurs sont en retard dans le support des templates (il faut les
bannir)
Enciaud (INRIA) C++ 16-18/02/2009 113 / 201
Templates
Presentation
Les familles en question sont parametrees par des types :
Ces types restent abstraits lors de lecriture du template en question
Il deviennent concrets lors de lutilisation de ces templates (`a la compilation)
Il est possible de denir des templates :
1
sur des structures ou des classes
2
sur des fonctions
1 // St r uc t ur e t empl at e , avec 3 ar guments :
2 // deux c l a s s e s I et U,
3 // un bool een par de f aut `a t r ue
4 templ ate <typename I , c l a s s U, bool B = tr ue>
5 s t r uc t s s t r u c t u r e {
6 / . . . /
7 };
8
9 // Fonct i on t empl at e , avec 3 ar guments
10 // un argument e x p l i c i t e bool een B
11 // deux ar guments i mp l i c i t e s de t ype U et V ( i n d e f i n i s )
12 templ ate <bool B, c l a s s U, c l a s s V>
13 bool f unc t i o n t e mpl a t e ( const U&, V) {
14 / . . . /
15 }
Enciaud (INRIA) C++ 16-18/02/2009 114 / 201
Templates
Exemple
Un exemple trivial de labstraction du type pour des fonctions...
Transformation
Algorithme type
Meta algorithme (int transforme en Tet tagge comme argument
template)
1 i n t maximum( const i n t i 1 , const i n t i 2 ) {
2 r et ur n i 1 > i 2 ? i 1 : i 2 ;
3 }
1 templ ate <c l a s s T>
2 T maximum(T i 1 , T i 2 )
3 {
4 r et ur n i 1 > i 2 ? i 1 : i 2 ;
5 }
Enciaud (INRIA) C++ 16-18/02/2009 115 / 201
Templates
Exemple & remarque
La fonction maximum sera alors appelable pour tout type T, MAIS avec les
conditions suivantes :
1
lalgorithme est valide si loperateur >existe pour le type T
2
la fonction prend des copies des objets et retourne une copie, ce qui nest pas
valide pour tout type T:
1 loperateur par recopie est correct pour lalgorithme (il retient linformation
permettant de faire la comparaison)
2 loperateur par recopie est correct pour la partie appelante (returnne
retourne pas une reference, mais une copie temporaire)
On commence `a comprendre pourquoi cest si seduisant, mais un peu delicat ?
Enciaud (INRIA) C++ 16-18/02/2009 116 / 201
Templates
Exemple (2)
Un exemple trivial de labstraction du type pour des structures...
Transformation
Structure typee Meta structure
1 s t r uc t s my s t r uc t {
2 i n t val ue 1 [ 1 0 ] ;
3 t ypedef f l o a t r e t u r n t y p e ;
4
5 r e t u r n t y p e oper at or ( ) ( ) {
6 i n t r e t = 0;
7 f or ( i n t i = 0; i < 10; i ++) r e t +=
val ue 1 [ i ] ;
8 r et ur n r e t / 10. f ;
9 }
10 };
1 templ ate <
2 c l a s s s t or a ge t y pe ,
3 i n t s i z e = 10 ,
4 c l a s s r e t u r n t y p e = f l oa t >
5 s t r uc t s my s t r u c t t {
6 s t o r a g e t y pe val ue 1 [ s i z e ] ;
7 t ypedef r e t u r n t y p e r e t u r n t y p e ;
8
9 r e t u r n t y p e oper at or ( ) ( ) {
10 s t o r a g e t y pe r e t = 0;
11 f or ( i n t i = 0; i < s i z e ; i ++)
12 r e t += val ue 1 [ i ] ;
13 r et ur n r e t / s i z e ;
14 }
15 };
Enciaud (INRIA) C++ 16-18/02/2009 117 / 201
Templates
Details
Il existe plusieurs mecanismes autour de lutilisation des templates :
1
la declaration et la denition
2
la specialisation totale ou partielle
3
la deduction (inference) de type pour les fonctions templates
Enciaud (INRIA) C++ 16-18/02/2009 118 / 201
Templates
Declaration & denition
La declaration commence par le mot clef template, suivi de :
1
<une liste de types >
2
class ou struct pour les classes et structures, ou un type de retour pour
les fonctions templates
3
le nom de la fonction ou de la structure/classe
4
les arguments pour une fonction template (entre parenth`eses)
5
optionnellement la denition du corps
6
et enn ;(point de terminaison)
Declaration
1 templ ate <c l a s s T> s t r uc t s t e mp l a t e t ; // s t r u c t u r e t empl at e
2 templ ate <c l a s s T> T f unc ( i nt , T) ; // f o n c t i o n t empl at e
Les declarations, classiquement, indiquent au compilateur que ces fonctions et ces
structures templates existent.
Elles indiquent egalement le nombre darguments abstraits dans le template (utile
pour la specialisation ou pour les arguments templates).
Enciaud (INRIA) C++ 16-18/02/2009 119 / 201
Templates
Liste des types admissibles
Les types admissibles dans la liste des type sont :
des types abstraits: class ou typenamesuivi de leur nom
des valeurs constantes connues au moment de la compilation, et du type :
entier, enum, pointeur, reference ou pointeur sur membre (le pointeur inclut
son naturellement le type pointe)
des classes templates
Il est possible davoir, pour les classes et structures templates, des arguments
templates par defaut (et qui peuvent referer `a des types precedents)
1 templ ate <c l a s s T, c l a s s U = i nt , c l a s s V = T>
2 s t r uc t s s t r u c t ;
3
4 // meme p r i n c i p e que pour l a s ur char ge , V non o p t i o n n e l ne peut s u i v r e un argument o p t i o n n e l
5 templ ate <c l a s s T, c l a s s U = i nt , c l a s s V>
6 s t r uc t s s t r u c t 2 ;
7
8 templ ate <c l a s s T, c l a s s U = i nt >
9 T f unc1 (T, U) ; // i n t e r d i t ! pas de de f aut s ur l e s f o n c t i o n s t e mpl at e s
Enciaud (INRIA) C++ 16-18/02/2009 120 / 201
Templates
Liste des types admissibles : valeurs
1 // r a ppe l : s t a t i c cons t i n t e s t d e f i n i s s a b l e dans l e c or ps de l a c l a s s e
2 templ ate <i n t I > s t r uc t s t e mpl a t e t 1 {
3 s t a t i c cons t i n t i = I ;
4 i n t j , k , l , m, o ;
5 };
6
7 s t e mpl a t e t 1 <20> o1 ; // ok
8
9 templ ate <bool B> s t r uc t s t e mpl a t e t 2 ;
10 s t e mpl a t e t 2 <tr ue> o2 ; // ok
11
12 bool b = f a l s e ;
13 s t e mpl a t e t 2 <b> o3 ; // e r r e u r : b v a r i a b l e ( i nconnu au moment de l a c ompi l a t i on )
14
15 const bool bc = f a l s e ;
16 s t e mpl a t e t 2 <bc> o4 ; // ok : bc c ons t ant
17
18 s t e mpl a t e t 1 <bc> o5 ; // ok : bool t r ue e v a l ue `a 1 , f a l s e e v a l ue `a 0
19
20 enum e v a l { val 1 , v a l 2 = 2};
21 templ ate <e v a l E> s t r uc t s t e mpl a t e t 3 ;
22 s t e mpl a t e t 3 <val 2 > o6 ; // ok
23 s t e mpl a t e t 3 <2> o7 ; // e r r e u r : e n t i e r n e s t pas enum !
Enciaud (INRIA) C++ 16-18/02/2009 121 / 201
Templates
Liste des types admissibles : valeurs (2)
Suite...
1
2 templ ate <f l o a t F> s t r uc t s t e mpl a t e t 4 ; // e r r e u r : f l o a t i n t e r d i t
3
4 s t a t i c char const c hai ne = "blablabla" ;
5 templ ate <chai ne > s t r uc t s t e mpl a t e t 5 ;
6
7 // t empl at e avec argument un po i nt e ur s ur f o n c t i o n ( r e t our na nt
8 // voi d et s ans par am`et r es )
9 templ ate <voi d (U) ( )> s t r uc t s t e mpl a t e t 6 ;
10
11 voi d f unc1 ( ) ;
12 s t e mpl a t e t 6 <&f unc1> o8 ; // ok
13 s t e mpl a t e t 6 <f unc1> o9 ; // e r r e u r : i l f a u d r a i t une r e f e r e n c e
14
15 templ ate <i n t I , i n t s t e mpl a t e t 1 <I >:: J> s t r uc t s t e mpl a t e t 7 {
16 s t e mpl a t e t 7 ( ) : v a l ue p ( J ) {}
17 i n t s t e mpl a t e t 1 <I >:: v a l ue p ; // po i nt e ur mutabl e
18 s t a t i c cons t i n t s t e mpl a t e t 1 <I >:: v a l u e p s ;
19 };
20 templ ate <i n t I , i n t s t e mpl a t e t 1 <I >:: J>
21 const i n t s t e mpl a t e t 1 <I >:: s t e mpl a t e t 7 <I , J >: : v a l u e p s = J ;
22
23 s t e mpl a t e t 1 <10> op ;
24 op . i = op . j = 20;
25 op . k = op . l = 30;
26
27 t ypedef s t e mpl a t e t 7 <10, &s t e mpl a t e t 1 <10>:: l > op2 t ;
28 op2 t op2 ;
29 s t d : : cout << op.op2 . v a l ue p << s t d : : e ndl ;
30 s t d : : cout << op.op2 . v a l u e p s << s t d : : e ndl ;
31 s t d : : cout << op.op2 t : : v a l u e p s << s t d : : e ndl ;
Enciaud (INRIA) C++ 16-18/02/2009 122 / 201
Templates
Liste des types admissibles : template
Il est egalement possible de mettre parmi les arguments, un autre template. Il doit
etre declare precisement avec la meme liste template que sa denition/declaration.
1 // de c l a r a t i o n de s t empl at e1 , s t empl at e2 , s t e mpl at e 3
2 templ ate <c l a s s A, i n t I >
3 s t r uc t s t e mpl at e 1 {/ . . . /};
4
5 templ ate <c l a s s A, i n t I >
6 s t r uc t s t e mpl at e 2 ;
7
8 templ ate <c l a s s A, c l a s s B, c l a s s C>
9 s t r uc t s t e mpl at e 3 {/ . . . /};
10
11 // de c l a r a t i o n de s t e mpl at e 4 ac c e pt ant un t empl at e en argument
12 // c e t argument t empl at e (A) a deux ar guments t empl at e : c l a s s et i n t
13 templ ate <templ ate <c l a s s A1 , i n t I 1> c l a s s A>
14 s t r uc t s t e mpl at e 4
15 {
16 A<i nt , 10> o p i nt ;
17 A<f l oa t , 40> o p f l o a t ;
18 // . . .
19 };
20
21 s t empl at e4 <s t empl at e1 > op1 ; // ok
22 s t empl at e4 <s t empl at e2 > op2 ; // non ok ! l e c or ps de s t e mpl at e 2 n e s t pas connu
23 s t empl at e4 <s t empl at e3 > op3 ; // e r r e u r s ur l a mi se en c or r e s pondanc e des ar guments
Enciaud (INRIA) C++ 16-18/02/2009 123 / 201
Templates
Espace de noms & champs de type
Un peu le meme principe que les namespace : utilisation de loperateur :: .
Denition (types complets)
Dans un template, les types complets sont les types connus :
soit parce que ce ne sont pas des types abstraits (constantes)
soit parce quils font partie de la liste darguments template
a
a. les arguments templates sont egalement des types
Denition (noms dependants)
Un nom dependant est un type quil nest possible de connatre quune fois le type
template compl`etement resolu.
R`egle
Les noms dependants doivent etre accedes via loperateur typename. Ce mot clef
indique au compilateur que le nom dependant est un type.
Il nest valide qu`a linterieur des templates.
Enciaud (INRIA) C++ 16-18/02/2009 124 / 201
Templates
Espace de noms & champs de type (2)
Syntaxe
1 templ ate <c l a s s T, c l a s s U>
2 s t r uc t A {
3 T t ;
4 U u ;
5 t ypedef typename T: : r e t u r n t y p e r e t u r n t y p e ; // champ membre de t ype T: : r e t u r n t y p e
6
7 A( const U&u = U( ) ) : t ( ) , u( u ) {}
8
9 r e t u r n t y p e oper at or ( ) ( ) const {
10 typename U: : c o n s t i t e r a t o r // v a r i a b l e s l o c a l e s de t ype U: : i t e r a t o r t y p e
11 i t = u . begi n ( ) ,
12 i t e = u . end ( ) ;
13 r et ur n t ( i t , i t e ) ; // T: : ope r a t or ( )
14 }
15 };
Enciaud (INRIA) C++ 16-18/02/2009 125 / 201
Templates
Exercice 1
1
Sabstraire des operations de recopies dans le template suivant :
1 templ ate <c l a s s T>
2 T maximum( const T i 1 , const T i 2 )
3 {
4 r et ur n i 1 > i 2 ? i 1 : i 2 ;
5 }
2
En faire un functor, qui sache renseigner ses types dentree et de sortie.
Enciaud (INRIA) C++ 16-18/02/2009 126 / 201
Templates
Exercice 2
Ecrire une structure template give me square, presentant une interface de tableau
indice operator [] , et retournant le carre de loperateur de fonction template
(functor- operator ()) suivant :
1 templ ate <
2 c l a s s s t or a ge t y pe ,
3 i n t s i z e = 10 ,
4 c l a s s r e t u r n t y p e = f l oa t >
5 s t r uc t s my s t r u c t t {
6 s t o r a g e t y pe val ue 1 [ s i z e ] ;
7 t ypedef r e t u r n t y p e r e t u r n t y p e ;
8
9 r e t u r n t y p e oper at or ( ) ( ) {
10 s t o r a g e t y pe r e t = 0;
11 f or ( i n t i = 0; i < s i z e ; i ++)
12 r e t += val ue 1 [ i ] ;
13 r et ur n r e t / s i z e ;
14 }
15 };
Ce mini exercice doit montrer comment interfacer correctement deux templates.
Enciaud (INRIA) C++ 16-18/02/2009 127 / 201
Templates
Exercice 3
1 templ ate <c l a s s T, c l a s s U>
2 s t r uc t A {
3 T t ;
4 U u ;
5 t ypedef typename T: : r e t u r n t y p e r e t u r n t y p e ; // champ membre de t ype T: : r e t u r n t y p e
6
7 A( const U&u = U( ) ) : t ( ) , u( u ) {}
8
9 r e t u r n t y p e oper at or ( ) ( ) const {
10 typename U: : c o n s t i t e r a t o r // v a r i a b l e s l o c a l e s de t ype U: : i t e r a t o r t y p e
11 i t = u . begi n ( ) ,
12 i t e = u . end ( ) ;
13 r et ur n t ( i t , i t e ) ; // T: : ope r a t or ( )
14 }
15 };
Exercice
Ecrire des classes Tet une classe Uqui soient compatibles avec la structure
template Aci-dessus. On pourra prendre par exemple pour U: une classe creee
par vos propres soins (si vous avancez vite), ou std :: vector(facile) ou encore
std :: map(un peu moins facile).
Exercice
Ecrire une fonction cliente de la structure Ade test.
Enciaud (INRIA) C++ 16-18/02/2009 128 / 201
Templates
Intanciation/appel explicite
Denition (appel explicite)
Le fait de specier tous les types est nomme lappel explicite
Exemple pour une classe
1 templ ate <c l a s s T> s t r uc t A {/ . . . /};
2 A<bool > op ;
Exemple pour une fonction
1 templ ate <c l a s s T>
2 bool f u n c t i o n t ( const T& t ) {/ . . . /}
3
4 bool b = f a l s e ;
5 b = f unc t i o n t <bool >(b) ;
6
7 t ypedef s t d : : vect or <i nt > v e c t i n t ;
8 v e c t i n t v a l ;
9 b = f unc t i o n t <v e c t i n t >( v a l ) ;
Enciaud (INRIA) C++ 16-18/02/2009 129 / 201
Templates
Inference de types
Denition (inference de types)
La deduction/inference des types est un mecanisme cote compilateur permettant
de decouvrir automatiquement les types (inference) en fonction des arguments de
lappel dune fonction template.
Exemple
1 templ ate <c l a s s T, c l a s s U>
2 bool my f unct i on ( c l a s s T& t , c l a s s U& u) {
3
4 typename T: : r e t u r n t y p e r e t u r n v a l u e ; // v a r i a b l e de t ype champ membre T: : r e t u r n t y p e
5
6 typename U: : c o n s t i t e r a t o r // v a r i a b l e s l o c a l e s de t ype U: : i t e r a t o r t y p e
7 i t = u . begi n ( ) ,
8 i t e = u . end ( ) ;
9 f or ( ; i t != i t e ; ++i t ) {
10 r e t u r n v a l u e += t ( i t ) ; // T: : ope r a t or ( )
11 }
12
13 r et ur n r e t u r n v a l u e > 1000; // exempl e de t r a ns f o r ma t i o n en bool een
14 }
Enciaud (INRIA) C++ 16-18/02/2009 130 / 201
Templates
Inference de types (2)
Il est possible dutiliser linference de type uniquement sur les types passes en
argument de lappel. Linference echoue donc
si certains types templates ne peuvent etre deduits de lappel
si certains types templates concernent les types de retour des fonctions
templates
Exemple 1 (qui ne fonctionne pas)
1 templ ate <c l a s s T, c l a s s U>
2 bool my f unct i on ( const T& t , const T& u) {
3 // . . .
4 }
Exemple 2 (qui ne fonctionne pas)
1 templ ate <c l a s s T, c l a s s U>
2 U my f unct i on ( const T& t , const T& u) {
3 // . . .
4 }
Enciaud (INRIA) C++ 16-18/02/2009 131 / 201
Templates
Inference de types : exercice
Enonce
Ecrire une fonction template qui ecrit dans std :: coutle type passe en argument
(la valeur ne nous interesse pas ici). On se servira le mot clef C++ typeid(T)et
la methode namede lobjet retourne typeid(T).name().
Attention : typeid
La sortie de typeidest compilateur dependant ! Il est utilise pour tester legalite
de types, mais non pour une sortie textuelle veritablement informative. typeid
retourne un objet CONSTANT type info (inclure le chier
#include <typeinfo>).
Enciaud (INRIA) C++ 16-18/02/2009 132 / 201
Templates
Specialisation
Denition (Specialisation)
La specialisation permet dindiquer que, pour un template donne, et pour une
combinaison particuli`ere de ses types, il existe une nouvelle version de ce template.
Syntaxe
1 templ ate <c l a s s T, c l a s s U>
2 s t r uc t s my t empl at e // de c l a r a t i o n de s my t empl at e
3 {
4 t ypedef T r e s u l t t y p e ;
5 };
6
7 templ ate <>
8 s t r uc t s my t empl at e <i nt , i nt > // s p e c i a l i s a t i o n de s my t empl at e pour l a combi nai s on i nt , i n t
9 {
10 t ypedef s my t empl at e <i nt , i nt > s e l f t y p e ; // l e cont enu de l a s p e c i a l i s a t i o n e s t compl `etement
d i f f e r e n t
11 };
12
13 s my t empl at e <f l oa t , bool > op ; // pr e mi `e r e v e r s i o n
14 s my t empl at e <i nt , i nt > op2 ; // deuxi `eme v e r s i o n
Enciaud (INRIA) C++ 16-18/02/2009 133 / 201
Templates
Specialisation totale/partielle
Notion FONDAMENTALE!
La specialisation est un mecanisme puissant qui rel`egue au compilateur les choix
des structures lors de la decouverte des param`etres templates.
Notion FONDAMENTALE! (bis)
La specialisation denit des NOUVEAUX TYPES. Une classe template et ses
specialisations nont RIEN DE COMMUN
a
.
a. en termes de contenu
Cf. exemples precedents : les classes s my template<U,V>et
s my template<int, int>sont des TYPES DIFFERENTS.
Denition (Specialisation totale)
Cest un type de specialisation o` u tous les types templates sont renseignes.
Cf. exemples precedents.
Enciaud (INRIA) C++ 16-18/02/2009 134 / 201
Templates
Specialisation totale/partielle
Denition (Specialisation partielle)
Cest un type de specialisation o` u certains types restent `a renseigner.
Syntaxe
1 templ ate <c l a s s T, c l a s s U>
2 s t r uc t s my t empl at e // de c l a r a t i o n de s my t empl at e
3 {
4 t ypedef T r e s u l t t y p e ;
5 };
6
7 templ ate <typename U>
8 s t r uc t s my t empl at e <i nt , U> // s p e c i a l i s a t i o n de s my t empl at e pour l a combi nai s on i nt , U
9 {
10 t ypedef s my t empl at e <i nt , U> s e l f t y p e ;
11 };
12
13 s my t empl at e <f l oa t , bool > op ; // pr e mi `e r e v e r s i o n
14 s my t empl at e <i nt , i nt > op2 ; // deuxi `eme v e r s i o n
Enciaud (INRIA) C++ 16-18/02/2009 135 / 201
Templates
Specialisation totale/partielle : exercice
Enonce
Ecrire une specialisation de la structure de copie suivante, lorsquelle est appelee
avec deux pointeurs constants sur entier (param`etre T) et un pointeur sur double
(param`etre U).
Structure `a specialiser
1 templ ate <c l a s s T, c l a s s U>
2 s t r uc t Copy {
3 voi d oper at or ( ) (T i t 1 , T i t 2 , U i t o u t )
4 {
5 f or ( ; i t 1 != i t 2 ; ++i t 1 , ++i t o u t )
6 {
7 i t o u t = i t 1 ;
8 }
9 }
10 };
Enonce
Ecrire une specialisation de cette meme structure, lorsquelle est appelee avec des
pointeurs de meme type (entier par exemple).
Enciaud (INRIA) C++ 16-18/02/2009 136 / 201
Templates
Specialisation & programmation incrementale
Supposons que nous avons un functor s do very weird things qui travaille
sur un ensemble de types T
i

Supposons que maintenant, nous avons une version amelioreede ce functor,


pour une combinaison C de ces types
Alors, il est possible dajouter cette version amelioreedans notre programme,
sans rupture de contratpour les appels existants. Le compilateur utilise alors la
version amelioree ou generale automatiquement, selon la combinaison de type.
On
a
appelle ce mecanisme la programmation incrementale : on commence par
une version tr`es generale, et ensuite on ajoute le particulier, sans retoucher le code
client existant.
a. enn je...
Cest donc le compilateur qui travaille plus que nous.
Enciaud (INRIA) C++ 16-18/02/2009 137 / 201
Meta-programmation
Programmation par templates : synth`ese
Meta-programmation ?
Resolution de nombreuses taches par le compilateur
1
Resolution des types
2
Specialisation
Fonction 1a
Mta-fonction 1
Fonction 1b Fonction 1c
Fonction 1
Fonction 2
Fonction 1a
Fonction 2a
Fonction 1b
Fonction 2b
Fonction 1
Fonction 2a Fonction 2b
Enciaud (INRIA) C++ 16-18/02/2009 141 / 201
Meta-programmation
Programmation par templates : synth`ese
Meta-programmation ?
Resolution de nombreuses taches par le compilateur
1
Resolution des types
2
Specialisation
Fonction 1
Fonction 2
Fonction 1a
Fonction 2a
Fonction 1b
Fonction 2b
Fonction 1
Fonction 2a Fonction 2b
Enciaud (INRIA) C++ 16-18/02/2009 141 / 201
Meta-programmation
Programmation par templates : synth`ese
Objectifs de la meta-programmation
1
Concentration des eorts sur le developpement des algorithmes
2
Capitalisation
3
Reutilisation ecace de lexistant
4
Portage algorithmique
Enciaud (INRIA) C++ 16-18/02/2009 142 / 201
STL
Functors - objets fonctionnels
<functional>
STL & conteneurs
<vector>
<map>
STL & algorithmes generiques
<limits>
<algorithm>
Enciaud (INRIA) C++ 16-18/02/2009 143 / 201
STL
Presentation
La STL (Standard Template Library) est une librairie standard
2
, distribuee avec
(pratiquement ?) tous les compilateurs C++.
Elle fournit des services minimaux, comme des structures template de container
(elements contenant), des algorithmes dexploitation et des classes utilitaires de
renseignement. Elle participe beaucoup `a la creation dalgorithmes templates.
Il faut tr`es souvent faire appel `a la STL
Utiliser la STL est bon pour votre productivite
2. ie. repondant `a des specications fonctionnelles strictes
Enciaud (INRIA) C++ 16-18/02/2009 144 / 201
Algorithmes generiques
Functors & objets fonctionnels - rappel
Denition (functor)
Un functor est une structure proposant linterface dune fonction.
Il sagit donc dun objet, qui est par denition plus riche quune fonction, et quil
est possible dappeler comme une fonction.
1 s t r uc t s f unc t o r dumb l i mi t e d {
2 // ! Sur char ge de l ope r a t e ur ope r a t or ( ) , i n d u i s a n t l e comportement de s i r e
3 bool oper at or ( ) ( const bool b) const throw ( ) { r et ur n ! b ; }
4 };
5
6 s f unc t o r dumb l i mi t e d op ;
7 a s s e r t ( ! op ( t r ue ) ) ;
Plus generalement, un functor permet de faire des choses plus puissantes que des
fonctions.
`
A ne pas confondre...
1 s f unc t o r dumb l i mi t e d op ; // de c l a r a t i o n d un o bj e t op de t ype s f unc t o r dumb l i mi t e d ;
2 s f unc t o r dumb l i mi t e d op ( ) ; // de c l a r a t i o n d une f o n c t i o n op , s ans par am`et r es et r e t our na nt un o bj e t
de t ype s f unc t o r dumb l i mi t e d
Enciaud (INRIA) C++ 16-18/02/2009 145 / 201
Algorithmes generiques
<functional>
Denition
<functional>Propose des functors utilitaires ainsi que des adapteurs pour creer
facilementdes functors.
Exemples :
1 // f unc t o r v e r s i o n de <, >, <=, >=
2 s t d : : l e s s , s t d : : gr e at e r , s t d : : l e s s e q u a l , s t d : : g r e a t e r e q u a l ;
3 s t d : : pl us , s t d : : mi nus , s t d : : mu l t i p l i e s , s t d : : d i v i d e s ; // +, , , /
std :: ptr fun
fonction template creant un functor `a partir dune fonction (binaire ou unaire)
1 // De c l a r a t i o n d une f o n c t i o n b i n a i r e
2 voi d f o n c t i o n b i n a i r e ( const i n t &, const f l o a t &) ;
3
4 // . . .
5 s t d : : l i s t <i nt > l ( 100) ;
6
7 // r e mp l i t l a l i s t e avec des nombres a l e a t o i r e s
8 s t d : : ge ne r at e n ( l . begi n ( ) , 100 , r and ) ;
9
10 // t r i e l a l i s t e avec un p r e d i c a t : not r e f o n c t i o n
11 // t r ans f or me e en f unc t o r
12 l . s o r t ( s t d : : p t r f u n ( f o n c t i o n b i n a i r e ) ) ;
Trouver les erreurs !
Enciaud (INRIA) C++ 16-18/02/2009 146 / 201
Algorithmes generiques
<functional> (2)
std :: bind1st/ std :: bind2nd: fonctions mettant un des deux param`etres dune
fonction binaire `a une constante
Le functor resultant devient unaire.
1 // De c l a r a t i o n d une f o n c t i o n b i n a i r e
2 i n t f o n c t i o n b i n a i r e ( const i n t &, const f l o a t &) ;
3
4 // g e ne r a t i on de s t d : : l i s t <i nt > l
5
6 // t r i e l a l i s t e avec not r e f o n c t i o n
7 s t d : : t r ans f or m (
8 l . begi n ( ) , l . end ( ) , l . begi n ( ) ,
9 s t d : : bi nd2nd (
10 s t d : : p t r f u n ( f o n c t i o n b i n a i r e ) ,
11 0. 34 f )
12 ) ;
Enciaud (INRIA) C++ 16-18/02/2009 147 / 201
<vector>
Tableau dynamique
Bon, tout le monde connat ?
Enciaud (INRIA) C++ 16-18/02/2009 148 / 201
<map>
Tableau associatifs
Denition (map)
Une mapest un tableau associatif : `a chaque clef, elle associe une valeur.
Le type de la clef et celui de la valeur sont les deux param`etres templates
obligatoires.
Un troisi`eme param`etre tr`es utile donne la fonction dordre sur la clef. Il vaut
par defaut le functor std :: less (inferant un ordre <sur lespace des clefs).
Lordre est donne par un functor, il est donc tr`es facile den denir un sur une
structure de clef complexe.
mapgarantie lunicite des clefs, mais selon le mod`ele suivant :
Soit k
1
et k
2
deux clefs, P est le predicat dordre.
P(k
1
, k
2
) P(k
2
, k
1
) k
1
equivalent `a k
2
Si la relation dordre nest pas correctement construite, on peut avoir des
mauvaises surprises.
Enciaud (INRIA) C++ 16-18/02/2009 149 / 201
<map>
Exercice
Enonce
Soit la structure suivante :
1 s t r uc t s my key {
2 i n t c o a r s e o r d e r ;
3 f l o a t f i n e o r d e r ;
4 };
1
La transformer pour quelle soit compatible avec std :: mapet avec lordre
par defaut. On souhaite associer s my key`a des chanes de caract`eres.
2
On souhaite avoir plusieurs ordres totaux. Proposez une approche avec des
functors.
1 s t d : : map<s my key , s t d : : s t r i n g > my map ;
2 s my key k [ 1 0 0 ] ;
3
4 f or ( i n t i = 0; i < 100; i ++) {
5 k [ i ] . c o a r s e o r d e r = 100 i 1;
6 k [ i ] . f i n e o r d e r = i / 10. f ;
7 s t d : : o s t r i ng s t r e a m o ;
8 o << "my_string_" << i << "_" << k [ i ] . c o a r s e o r d e r << "_" << k [ i ] . f i n e o r d e r ;
9 my map [ k ] = o . s t r ( ) ;
10 }
11 a s s e r t ( my map . count ( ) == 100) ;
Enciaud (INRIA) C++ 16-18/02/2009 150 / 201
<limits>
Renseignements numeriques
<limits>
<limits>contient des informations relatives aux types numeriques. Elle contient
principalement une classe template T, <numeric limits>qui donne des
informations sur le type numerique T.
Soit un type T, std :: numeric limit <T>denie des methodes statiques
(accessible sans instance) permettant dacceder `a un ensemble de fonctions
renseignant T:
1 s t d : : nume r i c l i mi t <T>: : max ( ) ; // f o n c t i o n s t a t i q u e r e t our na nt l e maximum p o s s i b l e pour l e t ype T
2 s t d : : nume r i c l i mi t <T>: : min ( ) ; // l e minimum p o s s i b l e pour l e t ype T
3 s t d : : nume r i c l i mi t <T>: : i s i n t e g e r ( ) ; // bool een i ndi qua nt que T e s t bi e n un t ype e n t i e r
4 s t d : : nume r i c l i mi t <T>: : e p s i l o n ( ) ; // v a l e u r i ndi qua nt l a l i mi t e numer i que d i n d i s t i n c t i o n e nt r e deux
T s u c c e s s i f s
Enciaud (INRIA) C++ 16-18/02/2009 151 / 201
<limits>
Exemple dutilisation
Initialisation correcte de lalgorithme en cas de liste vide :
Exemple sur linitialisation
Declaration Utilisation
1 templ ate <c l a s s T> typename T: : v a l ue t y pe
mi n o f c o l l e c t i o n (T i t , T i t e ) {
2 t ypedef typename T: : v a l ue t y pe v t ;
3 v t mi n val = s t d : : nume r i c l i mi t s <v t >: : max
( ) ;
4 f or ( ; i t != i t e ; ++i t )
5 i f ( mi n val < i t )
6 mi n val = i t ;
7 r et ur n mi n val ;
8 }
1 s t d : : vect or <i nt > v1 ;
2 s t d : : l i s t <doubl e> l 1 ;
3 f or ( i n t i = 0; i < 100; i ++) {
4 doubl e v a l = r and ( ) ;
5 v1 . pus h back ( s t a t i c c a s t <i nt >( v a l 1000 +
0. 5) ) ;
6 l 1 . pus h back ( v a l ) ;
7 }
8 s t d : : cout << mi n o f c o l l e c t i o n ( v1 . begi n ( ) , v1
. end ( ) ) << s t d : : e ndl ;
9 s t d : : cout << mi n o f c o l l e c t i o n ( l 1 . begi n ( ) , l 1
. end ( ) ) << s t d : : e ndl ;
Enciaud (INRIA) C++ 16-18/02/2009 152 / 201
Algorithmes generiques
Utilisation de <algorithm>
La partie <algorithm> de la STL propose une suite dalgorithmes frequemment
utilisees : tri, partition, ordre lexicographique, etc.
Les algorithmes se declinent generalement en plusieurs variantes qui se declinent
suivant les types en entree.
Exemple
1 voi d d o s o me s t u f f o n l i s t ( )
2 {
3 s t d : : l i s t <doubl e> l ( 100) ;
4 s t d : : ge ne r at e n ( l . begi n ( ) , 100 , r and ) ; // ge ne r at e n : ge ne r a t i o n de cont eneur par N a ppe l s `a une
f o n c t i o n
5 s t d : : l i s t <doubl e >: : i t e r a t o r i t = s t d : : f i n d ( l . begi n ( ) , l . end ( ) , 20) ; // r e c he r c he
6 i t = s t d : : max el ement ( l . begi n ( ) , l . end ( ) ) ; // i t e r a t e u r s ur l el ement maxi mal de l ensembl e
7 s t d : : s t a b l e s o r t ( l . begi n ( ) , l . end ( ) ) ; // or dr e pr e s e r v a nt l e s p o s i t i o n s r e l a t i v e s
8
9 s t d : : f o r e a c h ( l . begi n ( ) , l . end ( ) , s t d : : bi nd1s t ( s t d : : mu l t i p l i e s <doubl e >() , 3) ) ;
10
11 }
Enciaud (INRIA) C++ 16-18/02/2009 153 / 201
Patrons de
conception (Design
patterns)
Iterateurs
Singletons
Enciaud (INRIA) C++ 16-18/02/2009 154 / 201
Patrons de conception
Denition
Denition (Patron de conception)
Les patrons de conception (en anglais Design Patterns) sont des propositions de
conception informatiques largement eprouvees dans la resolution de probl`emes
genie logiciel types.
De nombreux patrons sont denis (cf. Wikipedia), nous en verrons quelques
uns
La STL utilise abondamment la notion diterateur qui est un patron de
conception
Le C++ se prete bien `a lutilisation de patrons...
Ameliore grandement le travail collaboratif (non intrusion de notions
complementaires, separation fonctionnelle...)
Mais les patrons de conception restent des propositions (pouvant vous donner des
idees) et suivre ces mod`eles nest pas une n en soi.
Enciaud (INRIA) C++ 16-18/02/2009 155 / 201
Patrons de conception
Iterateurs
Denition (Iterateur)
Un iterateur est un objet ayant une interface limitee, permettant de parcourir tout
ou partie dun objet contenant.
Avantage
Cet objet intermediaire de parcours isole lalgorithme client de la structure interne
du contenant : lalgorithme na pas besoin de connatre comment est constitue
lensemble quil doit parcourir.
Algorithme de moyenne
Exemple dutilisation... (trouver le bug)
1 templ ate <c l a s s T> f l o a t make my mean ( const T& c o nt a i ne r ) {
2 f l o a t m = 0;
3 i n t i nb = 0;
4 f or ( typename T: : c o n s t i t e r a t o r i t = c o nt a i ne r . begi n ( ) , i t e = c o nt a i ne r . end ( ) ;
5 i t != i t e ;
6 ++i t ) {
7 m += i t ;
8 i nb++;
9 }
10 r et ur n m / i nb ;
11 }
Enciaud (INRIA) C++ 16-18/02/2009 156 / 201
Patrons de conception
Iterateurs
Iterateur : interface
1
test de n diteration : pour un iterateur en C++, un couple diterateur est
necessaire : le premier it`ere, le second marque la n. Un test degalite permet
alors de determiner la n de literation
2
incrementation ou decrementation : avance ou recule literateur dun (ou
plusieurs) element(s)
le test de n est implemente en surchargeant loperator!=de la classe de
literateur
lincrementation est implementee en surchargeant loperator++de la classe
de literateur
Il existe deux versions de loperator++: le prexe (++it) et le post-xe
(it ++). Le premier ne prend pas dargument et retourne une reference sur
lui-meme (return this ). Le second prend un argument entier (non utilise) et
retourne une copie de lui-meme avant incrementation.
Enciaud (INRIA) C++ 16-18/02/2009 157 / 201
Patrons
Singletons
Denition (singleton)
Assure quune classe nest instanciee quune seule et unique fois.
Utile dans certains contextes : par exemple une classe de synchronisation de
ressources, une classe de mappage dev`enements, etc.
Exemple dimplementation
Template de singleton Classe singleton
1 templ ate <c l a s s T> c l a s s s i n g l e t o n {
2 s t a t i c T s i n g l e t o n o b j e c t ;
3 publ i c :
4 s t a t i c T& Ge t I ns t anc e ( ) {
5 r et ur n s i n g l e t o n o b j e c t ;
6 }
7 };
8
9 templ ate <c l a s s T>
10 T s i ng l e t o n <T>: : s i n g l e t o n o b j e c t = T( ) ;
1 // Ec r i r e l a c l a s s e Exempl eSi ngl et on
u t i l i s a n t l e t empl at e pr e ce de nt
2 c l a s s Exempl eSi ngl et on ;
Ecrire la classe ExempleSingleton(utilisation minimale du singleton).
Enciaud (INRIA) C++ 16-18/02/2009 159 / 201
Formation C++ avancee
J3 : Librairies externes et organisation de code
Enciaud (INRIA) C++ 16-18/02/2009 162 / 201
J3 : Librairies externes et organisation de code
Contenu
10
Librairies externes
11
Extension C++ avec Boost
12
Optimisation
Enciaud (INRIA) C++ 16-18/02/2009 163 / 201
Librairies externes
Compilation et edition de liens
Visibilite du code & interfaces
Enciaud (INRIA) C++ 16-18/02/2009 164 / 201
Librairies externes
Interfacage avec le C
Le C++ permet linterfa cage natifavec le C
Il faut pour cela que les types C soit correctement renseignes (au compilateur
C++) comme etant C.
Lorsque lon compile une unite de code en C++ :
1
la macro cplusplus est toujours denie (tout compilateur confondu)
2
la directive extern Cpermet alors de renseigner le type (structure, fonction)
Enciaud (INRIA) C++ 16-18/02/2009 165 / 201
Librairies externes
Interfacage avec le C : exemple
Exemple de declaration
Declaration dun header compatible avec le C et le C++ Utilisation
1 // f i c h i e r t ot o . h : header C/C++
2 #i f d e f c p l u s p l u s
3 ext er n "C" {
4 #e ndi f
5
6 #i nc l ude "header_c.h" // i n c l u s i o n de
de c l a r a t i o n C
7
8 s t r uc t s t o u j o u r s c {
9 i n t i ;
10 i n t t ab ;
11 / . . . /
12 };
13
14 voi d do pr oc e s s ( s t r uc t s t o u j o u r s c ) ;
15
16 #i f d e f c p l u s p l u s
17 } // ac c ol ade f er mat e e x t e r n C
18 #e ndi f
1 // f i c h i e r t ot o . cpp
2 #i nc l ude "toto.h"
3
4 c l a s s t ot o : publ i c s t o u j o u r s c {
5 t ot o ( ) : i ( 100) {}
6 voi d i n i t ( ) {
7 do pr oc e s s ( s t a t i c c a s t <s t o u j o u r s c >(
t h i s ) ) ;
8 }
9 };
10
11 // f i c h i e r t ot o . c
12 #i nc l ude "toto.h"
13
14 voi d do pr oc e s s ( s t r uc t s t o u j o u r s c s ) {
15 s>t ab = ( i n t ) mal l oc ( s . i s i z e o f ( i n t ) ) ;
16 / . . . /
17 }
Enciaud (INRIA) C++ 16-18/02/2009 166 / 201
Visibilite du code & interface
Remarques sur les inclusions
Remarque 1
Il nexiste pas de mecanisme trivial pour cacher des details dimplementation.
private/protected/publicne sont que des directives destinees au compilateur, et
indiquant approximativement lusage des membres dune classe.
Remarque 2
Le nombre de types utilises pour les implementations crot rapidement.
Pour quun utilisateur externe puisse utiliser une classe, il faut quil manipule tous
les types des methodes que cette classe appelle, ainsi que tous les types utilises
pour limplementation.
Ces deux points sont genants, `a la fois
pour le fournisseur (divulgation)
pour lutilisateur (pollution)
Enciaud (INRIA) C++ 16-18/02/2009 167 / 201
Visibilite du code & interface
Rappel
Interfaces
Les interfaces permettent darriver `a un resultat correct pour les deux parties, pour
un surco ut negligeable.
Elles laissent le soin au fournisseur de service de modier limplementation,
tant que linterface du service reste la meme
Elles empechent la divulgation de details dimplementation
Elles evitent au client le fardeau de la gestion de type lies `a limplementation
du fournisseur
Elles sont compatibles avec les templates et potentiellement la presence de
beaucoup de types
Elles restent souples `a manipuler pour le client
Enciaud (INRIA) C++ 16-18/02/2009 168 / 201
Extension C++
avec Boost
Presentation
Modes dutilisation & compilation
lesystem
Tests unitaires
Thread
Enciaud (INRIA) C++ 16-18/02/2009 169 / 201
Boost
Presentation
Boost (http ://www.boost.org) est un Consortium de developpeur C++,
travaillant sur des extensions standards du C++.
Licence
La licence dutilisation est dexploitation de Boost est permissive et non intrusive
(redistribution sans restriction dans des programmes `a but commercial ou non,
sans obligation de mention ni redistribution des sources).
Il faut utiliser Boost.
Utiliser Boost est une bonne chose, car Boost vous veut du bien.
Il faut convaincre tout le monde dutiliser Boost.
Boost est le prochain standard.
Enciaud (INRIA) C++ 16-18/02/2009 170 / 201
Boost
Modes dutilisation
Deux mani`ere dutiliser Boost :
1
version headers: `a inclure dans lunite de compilation concernee, et cest
tout (ex. : graph, mpl, proto, fusion, asio...)
2
version compilee : certaines (peu) parties de Boost necessitent une
compilation, et (donc) une liaison avec le programme client (ex. : lesystem,
regex, mpi,...)
Il faut utiliser Boost, cest simple `a installer.
Enciaud (INRIA) C++ 16-18/02/2009 171 / 201
Boost
Compilation et installation
Unises (Unix, Linux, Mac, Cygwin, ...)
1
$ cd path/to/boost_1_37_0
2
$ ./configure --prefix=path/to/installation/prefix
3
$ make install
Windows avec MS Visual Studio
1
Demarrer la ligne de commande Visual (normalement dans le menu demarrer
et dans le repertoire de Visual)
2
$ cd path/to/boost_1_37_0/tools/jam
3
$ build.bat
4
$ cd path/to/boost_1_37_0
5
$ copy path/to/-
boost_1_37_0/tools/jam/src/bin.Quelquechose/bjam .
6
$ bjam --build-dir=D:\temporary_dir --toolset=msvc --build-
type=complete stage
Enciaud (INRIA) C++ 16-18/02/2009 172 / 201
Boost
<boost/lesystem>
Objectif
Propose une abstraction plate-forme pour la manipulation du syst`eme de chiers.
Ex. : nom des chiers, gestion de larborescence, gestion des droits dacc`es,
existence, etc.
Il faut prealablement compiler la partie correspondante de Boost (with-lesystem
dans bjam), et lier (linker) avec boost lesystem lors de la creation du
programme.
Concatenation de repertoires
1 #i nc l ude <boos t / f i l e s y s t e m . hpp>
2 #i nc l ude <boos t / f i l e s y s t e m / f s t r e am . hpp>
3 namespace f s = boos t : : f i l e s y s t e m ;
4
5 f s : : path d i r ( "." ) ; // o bj e t de t ype path
6
7 f s : : path new p = d i r / "new_p" / "file_set" / "my_new_file" ; // ope r a t or / ov e r l oa d
8 new p . c r e a t e d i r e c t o r i e s ( new p . par e nt pat h ( ) ) ;
9
10 s t d : : of s t r eam my f i l e ( new p ) ;
11 my f i l e << "toto" << s t d : : e ndl ;
12 my f i l e . c l o s e ( ) ;
Enciaud (INRIA) C++ 16-18/02/2009 173 / 201
Boost
<boost/lesystem> : exemple
Determination du type dun chemin
1 #i nc l ude <boos t / f i l e s y s t e m . hpp>
2 namespace f s = boos t : : f i l e s y s t e m ;
3 // . . .
4 s t d : : s t r i n g f i l e na me = "my_file_or_file" ;
5 f s : : path f i l e ( f i l e na me ) ; // o bj e t de t ype path
6 i f ( ! f s : : e x i s t s ( f i l e ) )
7 s t d : : cout << "file \"" << f i l e na me << "\" does not exists !" ;
8
9 f s : : f i l e s t a t u s s t a t = f s : : s t a t u s ( f i l e ) ;
10 s t d : : cout << "This is a " ;
11 s wi t ch ( s t a t . t ype ( ) ) {
12 case f s : : r e g u l a r f i l e : // a f f i c h a g e de l a t a i l l e pour l e s f i c h i e r s
13 s t d : : cout << "regular file of size " << f s : : f i l e s i z e ( f i l e ) << s t d : : e ndl ;
14 br eak ;
15
16 case f s : : d i r e c t o r y f i l e : // l i s t e des f i c h i e r et nombre de f i c h i e r pour un r e p e r t o i r e
17 {
18 s t d : : cout << "directory containing " << s t d : : e ndl ;
19 i n t i = 0;
20 f or ( f s : : d i r e c t o r y i t e r a t o r i t r ( f i l e ) ; i t r != f s : : d i r e c t o r y i t e r a t o r ( ) ; ++i t r )
21 {
22 i ++;
23 s t d : : cout << "\t" << i t r >path ( ) . f i l e na me ( ) << s t d : : e ndl ;
24 }
25 s t d : : cout << s t d : : e ndl << i << " files" << s t d : : e ndl ;
26 }
27 br eak ;
28 de f a ul t :
29 s t d : : cout << "Unknown type" ;
30 br eak ;
31 }
32 // . . .
Enciaud (INRIA) C++ 16-18/02/2009 174 / 201
Boost
<boost/test>
But
Proposer un ensemble doutils pour ecrire des tests unitaires et de regression
robustes.
La librairie attend que nous denissions une fonction
1 boos t : : u n i t t e s t : : t e s t s u i t e i n i t u n i t t e s t s u i t e ( i n t ar gc , char ar gv [ ] ) ; // avec ar guments l i g n e de
commande
2 bool i n i t u n i t t e s t s u i t e ( ) ; // pl us s i mpl e
Le corps de cette fonction va declarer nos suites de tests, de la mani`ere suivante :
1 voi d t e s t c a s e 1 ( ) ;
2 t e s t s u i t e i n i t u n i t t e s t s u i t e ( ) {
3 t e s t s u i t e t s 1 = BOOST TEST SUITE( "test suite 1" ) ;
4 t s1>add (BOOST TEST CASE(&t e s t c a s e 1 ) ) ;
5 }
Les tests ne demarreront quau retour de cette fonction de de declaration.
Enciaud (INRIA) C++ 16-18/02/2009 177 / 201
Boost
<boost/test> : exemple
Exemple de test
1 voi d t e s t c a s e 1 ( ) {
2 BOOST CHECK(1 == 1) ; // t e s t 1
3 BOOST CHECK MESSAGE(1 == 2 , "seems that 1 != 2" ) ; // t e s t echoue avec un message , mai s i l c ont i nue
4 BOOST CHECK THROW( throw s t d : : r unt i me e x c e pt i on ( "blablabla" ) , s t d : : r unt i me e x c e pt i on ) ; // t e s t de throw
5 BOOST ERROR( "message derreur" ) ; // message d e r r e u r et e r r e u r e n r e g i s t r e e
6
7 BOOST CHECH EQUAL(2+2 , 4) ; // t e s t
8
9 BOOST REQUIRE( t r ue ) ; // d o i t e t r e v r a i pour c o nt i nue r ce t e s t .
10 }
Enciaud (INRIA) C++ 16-18/02/2009 178 / 201
Boost
<boost/thread.hpp>
Objectif
Propose une abstraction plate-forme pour la manipulation des threads.
Propose des manipulateurs haut niveau pour la gestion des threads.
Il faut prealablement compiler la partie correspondante de Boost (with-thread
dans bjam), et linker avec boost threadlors de la creation du programme.
Quelques objets de boost : :thread
1 boos t : : t hr e ad t ; // un t hr e ad
2 boos t : : t hr e ad gr oup g ; // gr oupe de t hr e a ds
Enciaud (INRIA) C++ 16-18/02/2009 179 / 201
Boost
<boost/thread.hpp> : exemple de functor
Objet fonctionnel dont le corps sera execute dans un thread
1 #i nc l ude <boos t / t hr e ad / t hr e ad . hpp>
2 #i nc l ude "boost/date_time/posix_time/posix_time_types.hpp"
3 us i ng namespace boos t : : po s i x t i me ; // pour l e s s l e e p s
4
5 s t r uc t my f unct or {
6 i n t i n i t v a l u e 1 ;
7 my f unct or ( i n t i n i t v a l u e 1 ) : i n i t v a l u e 1 ( i n i t v a l u e 1 ) {}
8 // c or ps du t hr e ad
9 voi d oper at or ( ) ( )
10 {
11 boos t : : t h i s t h r e a d : : d i s a b l e i n t e r r u p t i o n di ;
12 {
13 s t d : : cout << "Thread (functor) inited with " << i n i t v a l u e 1 << s t d : : e ndl ;
14 s t d : : cout << "Thread id is " << boos t : : t h i s t h r e a d : : g e t i d ( ) << s t d : : e ndl ; // i d e n t i f i a n t
15 }
16
17 i n t count = 0;
18 whi l e ( ! boos t : : t h i s t h r e a d : : i n t e r r u p t i o n r e q u e s t e d ( ) ) // t e s t de demande d i n t e r r u p t i o n
19 {
20 // s e c t i o n s ans i n t e r r u p t i o n
21 boos t : : t h i s t h r e a d : : d i s a b l e i n t e r r u p t i o n di ;
22 {
23 s t d : : cout << "." << count++ << s t d : : e ndl ;
24 i f ( count % i n i t v a l u e 1 )
25 s t d : : cout << s t d : : e ndl ;
26 }
27 boos t : : t h i s t h r e a d : : s l e e p ( t i me dur a t i o n ( 0 , 0 , 0 , 100) ) ; // s l e e p de 2 s econdes
28 }
29 }
30 };
Enciaud (INRIA) C++ 16-18/02/2009 180 / 201
Boost
<boost/thread.hpp> : exemple dappel
Programme de test (sur un groupe de threads)
1 voi d t e s t ( ) {
2 boos t : : t hr e ad gr oup g ; // gr oupe de t hr e ad
3
4 f or ( i n t i = 1; i < 10; i ++)
5 {
6 boos t : : t hr e ad my t hr ead = new boos t : : t hr e ad ( my f unct or ( i 300) ) ;
7 // boos t : : t hr e ad my t hr ead ( my f unct or ( i 300) ) ;
8 g . add t hr ead ( my t hr ead ) ;
9 }
10 s t d : : cout << "Init end" << s t d : : e ndl ;
11 char c = 0;
12 s t d : : cout << "Press a key" << s t d : : e ndl ;
13 whi l e ( ! ( s t d : : c i n >> c ) ) {
14 }
15
16 g . i n t e r r u p t a l l ( ) ; // l a nc e un s i g n a l d i n t e r r u p t i o n
17 g . j o i n a l l ( ) ; // at t end l a f i n de t ous l e s t hr e a ds
18
19 s t d : : cout << "end of all threads" << s t d : : e ndl ;
20 }
Enciaud (INRIA) C++ 16-18/02/2009 181 / 201
Optimisation
Questions generales
Conteneurs
Optimisations logicielles
Enciaud (INRIA) C++ 16-18/02/2009 183 / 201
Optimisation
Questions generales autour du C++
Premature optimization is the root of all evil(Donald Knuth)
Que veut dire optimisation ?
On optimise toujours en fonction dune ou plusieurs contraintes... Ex. : temps de
calcul, occupation memoire, algorithmique...
Les contraintes sont parfois contradictoires et/ou conictuelles.
Denition (Co ut algorithmique)
Co ut theorique de lalgorithme exprime par rapport `a la taille N des donnees
traitees et exprime en O((N)), pour N N

.
: 1 (temps constant), identite, polynome, log...
Enciaud (INRIA) C++ 16-18/02/2009 184 / 201
Optimisation
Questions generales autour du C++
Rappels importants
1
Le co ut est asymptotique, cest-`a-dire exprime pour N grand (ce qui nest pas
systematiquement le cas).
2
O((N)) est vrai `a une constante pr`es, qui peut etre potentiellement
importante !
Enciaud (INRIA) C++ 16-18/02/2009 185 / 201
Optimisation
Questions generales autour du C++
Questions classiques :
1
Le C++ est plus lent que le C : vrai ou faux ?
Reponse mitigee. Dexperience : vrai pour des parties isolees de code, faux
pour des projets denvergure importante. Meme debat entre le C et
lassembleur par exemple...
2
O` u et quand optimiser ?
Une fois quon a enn un truc qui fonctionne, selon un design relativement
correct.
Remarque : les contraintes inuencent necessairement la phase de design,
donc inutile de faire de loptimisation logicielle trop tot.
3
Comment optimiser ?
Encore une fois, selon la contrainte.
Nous allons voir quelques elements doptimisation algorithmique et logicielle...
Enciaud (INRIA) C++ 16-18/02/2009 186 / 201
Optimisation
Choix des conteneurs
Alerte ! Alerte ! Alerte !
Le choix du conteneur est FONDAMENTAL !
Le choix est dirige par lutilisation quon compte en faire :
1
Si lordre dinsertion est important
2
Si on va parcourir lensemble contenu (co ut et performance des iterateurs)
3
Si on va inserer des elements relativement `a dautres (et non simplement en
debut ou n)
4
...
Les co uts dacc`es des conteneurs standards sont egalement standards ! Donc
garantie multi plate-forme.
Enciaud (INRIA) C++ 16-18/02/2009 187 / 201
Optimisation
Choix des conteneurs (1)
std : :vector
1
ajout delement en debut ou n en O(1)
2
acc`es aux elements en O(1)
3
requete de taille en O(1)
4
parcours en
v
O(N), avec
v
1, avec possibilite davoir
v
< 1
5
insertion delement en O(N) (recopie) ! dramatique, ne pas faire avec
vecteur...
Enciaud (INRIA) C++ 16-18/02/2009 188 / 201
Optimisation
Choix des conteneurs (2)
std : :list
1
ajout delement en debut ou n en O(1)
2
acc`es aux elements en O(N) : mauvais
3
requete de taille en O(1) `a verier
4
parcours en
l
O(N), avec
l
1, mais
l
>
v
5
insertion delement en O(1) ! bon point !
Enciaud (INRIA) C++ 16-18/02/2009 189 / 201
Optimisation
Comprendre et gerer la bidouille de compilateurs
Idee
Faire en sorte que le compilateur aille plus loin dans la generation dun code
rapide et/ou compact.
Code rapide :
Activer les ags doptimisation

Choix du compilateur ! !

Options doptimisation de plusieurs niveaux (GCC : O1, O2, 03, O45... active
un ensemble doptimisations)

Choix du processeur cible

Utilisation automatique de librairies externes (open MP, etc)

Profondeur des inlines

Utilisation des fonctions intrins`eques

Optimisations globales `a ledition de lien

...
Avantage important : methode doptimisation non-intrusive
Enciaud (INRIA) C++ 16-18/02/2009 191 / 201
Optimisation
Comprendre et gerer la bidouille de compilateurs
Code rapide (suite) :
...
Utilisation des inlines
1
Methode doptimisation intrusive !
2
Pas vraiment une optimisation : le choix de linlining reste le choix du
compilateur
Utilisation de portions de code assembleur
1
Tr`es performant (souvent, mais pas toujours)
2
Tr`es specique
3
Dur
4
Tr`es dur meme...
5
Dicile `a maintenir
6
Plate-forme dependant
Enciaud (INRIA) C++ 16-18/02/2009 192 / 201
Formation C++ avancee
Synth`ese de la formation
Enciaud (INRIA) C++ 16-18/02/2009 196 / 201
Synth`ese de la formation
Contenu
Enciaud (INRIA) C++ 16-18/02/2009 197 / 201
Un outil `a matriser
Tenir compte des risques
Le code est meilleur et plus compact mais :
risque dhubris
a
(donc perte de focalisation)
probl`emes de lourdeur (design, dev, execution)
a. Chez les Grecs, tout ce qui, dans la conduite de lhomme, est considere par les dieux comme
demesure, orgueil, et devant appeler leur vengeance.
Risque majeur :
Quand on est lances, pourquoi sarreter `a ce dont on a besoin ? !
Enciaud (INRIA) C++ 16-18/02/2009 198 / 201
Savoir-faire
Pour etre performant, il faut :
matriser le plus grand nombre detrucs
en connatre les avantages/inconvenients
specier d`es le debut (notamment les perfs)
Et pour ca
le mieux est den faire beaucoup et den jeter beaucoup. Iterer.
Enciaud (INRIA) C++ 16-18/02/2009 199 / 201
La genericitelight
design for change
Commencer simple (YAGNI)
a
Rendre le code generic-friendly
Concevoir pour levolutif
a. You Aint Gonna Need It
Limportant
cest de se fermer le moins doptions, tout en restant optimal sur ce quon fait
maintenant.
Enciaud (INRIA) C++ 16-18/02/2009 200 / 201
Merci de votre attention
Release early, release often...
Enciaud (INRIA) C++ 16-18/02/2009 201 / 201