1242.2 Langage C++ - 2024-2025
1. Introduction
2.
3.
4.
5.
6. RTTI
Les conversions (cast) peuvent être faites par des mots-clés dédiés
Syntaxe
Exemple
int i = 100;
char c = static_cast<char>(i); // int -> char
float f = 100.0f;
i = static_cast<int>(f); // float -> int
class Base{};
class Deri : public Base{};
Der *d = new Deri;
Base *b = static_cast<Base*>(d); // Deri* -> Base*
char c = 10; // 1 byte
int *p = (int*)&c; // 4 bytes
*p = 5; // run-time error: stack corruption
int *q = static_cast<int*>(&c); // compile-time error
float *pf=&f;
double *pd=&d;
pd = static_cast<double*> (pf); // ⛔ error
pd = reinterpret_cas<double*>v(pf); // ✅ ok
*aucune donnée n'est physiquement modifiée, ce n'est qu'une indication pour le compilateur
int i;
char *ptr = reinterpret_cast<char*>(i); // int -> char*
char &ref = reinterpret_cast<char&>(i); // int -> char&
float *pf = reinterpret_cast<float*>(pd); // double* -> float*
Utile pour scanner de la mémoire (scanner un range de int avec reinterpret_cast<char*>(adr) pour voir byte par byte le codage, faire un désassembleur, déc)
class A{};
const A *cptr;
A *ptr = const_cast<A*>(cptr); // const A* -> A*
A a;
const A &cref = a;
A &ref = const_cast<A&>(cref); // const A& -> A&
Opérateur peu utile, car :
- la conversion non-const ⇒ const est implicite
- la conversion const ⇒ non-const relève souvent d'une erreur de conception
- le qualificatif
Il est utilisé pour supprimer la constance des références et des pointeurs qui se réfèrent à quelque chose qui, à la base, n'est pas const
Les seules possibilités de conversion sont
⇒ elle doit comporter au moins une fonction membre virtuelle
⇒ être manipulée au moyen d'un pointeur ou d'une référence
Ce type de cast est dynamique (effectué à l'exécution), et est susceptible d'échouer :
⇒ renvoie
⇒ lève une exception
Product *products[100];
for (int i = 0; i < 100; i++)
{
Liquor *ptrLiquor = dynamic_cast<Liquor*>(products[i]);
if (nullptr != ptrLiquor)
cout << ptrLiquor->degree() << endl;
else
cout << products[i]->name();
}
- La fonction que l'on écrit ne travaille en fait pas sur la classe de base, mais seulement sur certaines classes dérivées bien identifiées
- Polymorphisme dynamique pas exploité (fonctions virtuelles)
- Polymorphisme statique pas exploité (utilisation de templates, surcharges)
- Hiérarchie de classes mal structurée
Permet de déterminer le type d'une variable à l'exécution (runtime)
Le mécanisme RTTI contient :
- Le mot-clé de conversion
- L'opérateur
⇒ utilisé pour vérifier le type d'un objet à l'exécution
typeid(int).name() // ⇒ i
typeid(float).name() // ⇒ f
typeid(2+2.00).name() // ⇒ d
typeid(ptri).name() // ⇒ Pi
typeid(ptrf).name() // ⇒ Pf
typeid(refd).name() // ⇒ d
AAA a;
typeid(a).name() // ⇒ Z4mainE3AAA
class Animal { public: virtual ~Animal(){}};
class Mammifere : public Animal {};
class Chien : public Mammifere {};
class Caniche : public Chien {};
int main() {
Animal *ptr = new Caniche;
typeid(ptr).name(); // ⇒ P6Animal
typeid(*ptr).name(); // ⇒ 7Caniche
typeid(*ptr) == typeid(Chien); // ⇒ Faux
typeid(*ptr) == typeid(Caniche); // ⇒ Vrai
return 0;
}
if (typeid(*ptr) == typeid(Chien)) {
Chien *c = dynamic_cast<Chien*>(ptr);
if (c) {
// ptr est un Chien
}
}