Vous êtes sur la page 1sur 0

Centre Informatique pour les Lettres

et les Sciences Humaines


Apprendre C++ avec Qt : Annexe 5
Run-Time Type Information

Le RTTI est un dispositif qui permet de dterminer le type de l'objet dont l'adresse est contenue
dans un pointeur sur une classe de base (il peut lgitimement s'agir d'une instance de la classe
de base ou d'une instance de n'importe laquelle des classes drives de celle-ci).

Etant donn qu'un pointeur sur une classe de base ne doit normalement servir qu' appeler
des fonctions de cette classe (qui peuvent, ventuellement, tre virtuelles et redfinies dans les
classes drives), il n'est habituellement pas ncessaire de connatre le type exact de l'objet
qu'il dsigne (la virtualit des fonctions redfinies suffit garantir que c'est le code adapt au
type concern qui sera excut). Nous pouvons donc conclure que

Un programme "normal" ne fait jamais appel au RTTI.

S'il s'agit de dbuguer un programme ou simplement d'explorer le fonctionnement des
fonctions virtuelles, le recours au RTTI peut cependant s'avrer instructif, ou mme trs utile.
1 - L'oprateur t ypei d et la classe t ype_i nf o
L'oprateur t ypei d( ) renvoie une rfrence une constante de type t ype_i nf o correspondant
au type de l'objet auquel il est appliqu.

Typiquement, cet objet est dsign en drfrenant un pointeur sur une classe de base.

Une valeur de type t ype_i nf o dcrit un type sous une forme utilisable par un programme. Il
est ainsi possible de comparer deux valeurs (avec les oprateurs == et ! =) et d'obtenir une
chane de caractres correspondant au nom utilis dans le code source pour dsigner le type.
Ainsi, aprs

cl ass CBase 1
{ 2
publ i c: 3
vi r t ual voi d m_f ( ) {} 4
}; 5

cl ass CDer i vee : publ i c CBase 6
{ 7
publ i c: 8
i nt m_pr opr e; 9
}; 10

l'excution du fragment de code suivant

CDer i vee unD; 1
CBase * pt r = &unD; 2
const t ype_i nf o & l eType = t ypei d( *pt r ) ; 3
QSt r i ng l aCl asse = l eType. name( ) ; 4

placera dans la variable l aCl asse la chane cl ass CDer i vee

L'utilisation de la classe t ype_i nf o exige la prsence d'une directive #i ncl ude " t ypei nf o. h"

Si vous utilisez Visual C++ 6.0, vous devez aussi cocher la case "Enable RTTI" dans l'onglet
"C/C++" (category "C++ langage") de vos "Projects settings".

Notez galement que

L'oprateur t ypei d( ) ne donne rellement le type de l'objet point que si la classe de base
concerne possde au moins une fonction virtuelle.

Document du 23/08/05 - Retrouvez la version la plus rcente sur http://www.up.univ-mrs.fr/wcpp
C++ - Annexe 5 RTTI 2/2

2 - L'oprateur dynami c_cast < >
Lorsqu'un pointeur sur une classe de base contient l'adresse d'une instance d'une classe
drive, l'oprateur dynami c_cast < >permet de convertir cette valeur en un pointeur sur la
classe drive en question (ce qui permettra d'accder aux membres propres qu'elle dfinit). Si
l'objet point n'est pas du type attendu (il peut s'agir d'une simple instance de la classe de
base, par exemple), la valeur produite par dynami c_cast < >est nulle.

C'est cette dernire caractristique qui justifie l'existence de dynami c_cast < >. L'usage d'un
st at i c_cast < >ou d'un r ei nt er pr et _cast < >permet en effet d'obtenir n'importe quelle
conversion entre type de pointeurs, mais sans aucune vrification de cohrence

/ / l es cl asses CBase et CDer i vee sont supposes df i ni es comme pr cdemment 1
voi d f onct i onSauvage( CBase *pt r Base) 2
{ 3
CDer i vee * pt r Der i vee = dynami c_cast <CDer i vee *> ( pt r Base) ; 4
i f ( pt r Der i vee ! = NULL) 5
pt r Der i vee- >m_pr opr e = 4; 6
} 7

Si la fonction ci-dessus permet d'illustrer l'usage de l'oprateur dynami c_cast < >, elle permet
galement d'expliquer pourquoi ce type de conversion (connue sous le nom de "downcasting",
parce qu'elle permet de "descendre" dans la hirarchie des classes) n'est gnralement pas
souhaitable.

Remarquons tout d'abord que cette fonction, qui n'est membre ni de CBase ni de CDer i vee,
prtend accder une variable membre. Ce simple fait est dj une hrsie, puisque l'interface
d'une classe ne doit comporter que des fonctions membre.

En quoi la situation serait-elle diffrente s'il s'agissait d'appeler une fonction membre de
CDer i vee et non d'accder une de ses variables ? Dans ce contexte, la simple vocation d'une
fonction membre appelle la question "Pourquoi n'est-elle pas virtuelle ?"

Si la classe CBase comporte une fonction virtuelle nomme r emi seEnEt at I ni t i al ( ) , par
exemple, cette fonction peut tre redfinie par les classes drives, qui sont les seules
vraiment savoir ce qu'il convient de faire avec leurs membres propres.

La version redfinie dans CDer i vee se chargera, par exemple, d'affecter la valeur 4 la
variable m_pr opr e.

Le code de la f onct i onSauvage( ) devient alors

voi d f onct i onSauvage( CBase *pt r Base) 1
{ 2
pt r Base- >r emi seEnEt at I ni t i al ( ) ; 3
} 4

Non seulement ce code est plus court et plus clair, mais il fait quelque chose dont la version
initiale de la fonction tait bien incapable : il traite correctement le cas de toutes les classes
drives de CBase, qu'elles soient prsentes ou venir.

Il est concevable que la fonction propre qui doit tre excute soit tellement spcifique la
classe drive concerne que la cration d'une fonction virtuelle dans la classe de base
semble franchement draisonnable. Une autre piste doit alors tre explore : pourquoi la
f onct i onSauvage( ) n'est-elle pas elle-mme une fonction virtuelle de la classe de base ? Elle
pourrait alors tre facilement redfinie par les classes ncessitant des traitements trs
spcifiques (et par elles seules), et ces redfinitions pourraient, le cas chant, appeler
explicitement la version de base de la fonction, pour viter de s'occuper d'autre chose que de
la spcificit qui justifie leur existence.

Nous pouvons donc conclure que

Un programme "normal" ne fait jamais appel l'oprateur dynami c_cast < >.

J-L Pris - 23/08/05