Main menu:

Site search

Categories

mai 2008
L M M J V S D
 1234
567891011
12131415161718
19202122232425
262728293031  

Archive

C++ – Conversions de type (casting)

Contrairement au C, C++ propose 4 types de conversions (casts) spécialisés. Mais en quoi est-ce mieux d’utiliser les casts spécialisés par rapport au cast du C?

En C, on place entre parenthèses le type vers lequel la conversion doit se faire. Par exemple pour convertir un Objet en int, on écrit:

int i;
i = (int)Objet;

Ce type de cast permet tout à la fois de convertir un type dans un autre, convertir un pointeur d’une classe dérivée en un pointeur vers sa classe de base, convertir un pointeur de la classe de base vers un pointeur d’une classe dérivée (downcasting et upcasting)…
En fait il permet de convertir n’importe quoi en n’importe quoi et donc en quelque sorte de mentir au compilateur. C’est pourquoi, c’est plus que déconseillé en C++.

En C++, même si ce type de cast existe toujours, il existe 4 types de casts différents et chacun utilisable dans un domaine de conversion bien défini. L’avantage c’est que s’ils sont utilisés à mauvais escient, ils renvoient une erreur ou ne compilent pas. Ils sont plus clairs et plus concis et utilisent une syntaxe proche des templates. Il n’y a en principe pas d’ambiguité entre les différents types de cast. Le cast effectué au moment du runtime (quand le programme tourne) permet au programmeur de tester le résultat de la conversion.

Static cast

static_cast <Type>(t) est utilisé dans des situation où on doit caster un pointeur vers une classe de base en un pointeur vers une classe dérivée (downcast). Il n’y a pas de restriction concernant le caractère polymorphique de la classe.  Il sert aussi à convertir un int en un enum, à convertir une référence d’un type vers une référence d’un autre type et en règle générale, un objet d’un type vers un objet d’un autre type (par exemple un int vers un double).

Dynamic cast

dynamic_cast<Type>(t) ne peut être utilisé que pour un pointeur ou une référence. Deux conditions sont nécessaires pour pouvoir utiliser dynamic_cast:

  • dynamic_cast n’est utilisable qu’avec des classes polymorphiques, c’est à dire qui contiennent au moins une fonction virtuelle.
  • il faut que t soit réellement du type Type ou qu’il soit d’un type dérivé de Type. Si ce n’est pas le cas, dynamic_cast renvoie 0 dans le cas d’un pointeur et lève une exception de type bad_cast s’il s’agit d’une référence.

Note: convertir un pointeur d’un type dérivé vers un type de base est implicite en C++. Il n’est pas nécessaire d’utiliser dynamic_cast ou static_cast.

Reinterpret cast

reinterpret_cast<Type>(t) permet de convertir n’importe quel pointeur ou type intégral en un autre type. Ce type de cast est pratiquement aussi peu sûr que le cast en C et ses domaines d’application sont plutôt restreints. Il ne peut pratiquement que servir à convertir d’un type vers un autre puis à revenir dans le type original par un nouveau cast. Sa seule différence avec le cast C est que reinterpret_cast ne permet pas de retirer le caractère constant d’un objet contrairement au cast C.

Const cast

Les trois types de casts précédents ne permettent pas de retirer le caractère constant d’un objet. Pour retirer l’attribut constant d’un objet vous utiliserez const_cast<Type>(t). Le type de retour est identique au type qui est casté. Autrement dit:

class B {};
class D : public B {};

int main()
{
  const B* cb = new B;
  const D* cd = new D;

  B* b = const_cast<B*>(b);       // Ok
  D* d = const_cast<D*>(d);       // Ok 
  B* bb = const_cast<B*>(d);      // Erreur  
  D* dd = const_cast<B*>(b);      // Erreur  

  return 0;
}

Comments

Comment from Yoms
Time: 24 mars 2010, 19 h 46 min

Merci pour cette page qui m’a bien aidé ^^