Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
En C++, si une classe est dérivée d’une classe de base contenant une ou plusieurs fonctions virtuelles, un pointeur vers ce type de classe de base peut être utilisé pour appeler des fonctions virtuelles dans l’objet de classe dérivé. Une classe contenant des fonctions virtuelles est parfois appelée une classe polymorphe.
Hiérarchie de classes
Un objet de type C
peut être visualisé comme suit :
Classe C avec sous-objets B et A
Étant donné une instance de classe C
, il existe un sous-objet B
et un sous-objet A
. L'instance de C
, avec les sous-objets A
et B
forme l'objet complet.
Puisque qu’une classe dérivée contient complètement les définitions de toutes les classes de base à partir desquelles elle est dérivée, il est sûr de convertir un pointeur vers l’une de ses classes de base (opération souvent appelée upcast). Étant donné un pointeur vers une classe de base, il peut être pertinent de convertir ce pointeur en une instance d’une classe dérivée (également appelée downcast).
À l’aide d’informations de type d’exécution, il est possible de vérifier si un pointeur pointe réellement vers un objet complet et peut être converti en toute sécurité pour pointer vers un autre objet de sa hiérarchie. L’opérateur dynamic_cast effectue une vérification au moment de l’exécution pour s’assurer que l’opération est sécurisée. Il est préférable de concevoir votre hiérarchie de classes afin de pouvoir utiliser des fonctions virtuelles pour éviter tout besoin de downcasting. Toutefois, si vous devez effectuer un downcast, utilisez dynamic_cast
pour vous assurer que l’opération est sécurisée.
Pour la conversion de types non polymorphiques, vous pouvez utiliser l’opérateur static_cast (cette rubrique explique la différence entre les conversions de cast statiques et dynamiques, et quand il est approprié d’utiliser chacune).
L’exemple suivant montre l’utilisation de dynamic_cast
et static_cast
:
#include <iostream>
class Base {
public:
virtual void print() { std::cout << "Base\n"; }
};
class Derived1 : public Base {
public:
void print() override { std::cout << "Derived1\n"; }
};
class Derived2 : public Base {
public:
void print() override { std::cout << "Derived2\n"; }
};
class MostDerived : public Derived1, public Derived2 {
public:
void print() override { std::cout << "MostDerived\n"; }
};
int main() {
MostDerived md;
Base* b1 = static_cast<Derived1*>(&md); // Upcast to Derived1 is safe
Base* b2 = static_cast<Derived2*>(&md); // Upcast to Derived2 is safe
// Downcast to MostDerived is ambiguous and unsafe
// MostDerived* md1 = static_cast<MostDerived*>(b1); // This won't compile
// MostDerived* md2 = static_cast<MostDerived*>(b2); // This won't compile
// Correct way to downcast in this situation
MostDerived* md1 = dynamic_cast<MostDerived*>(b1); // This is safe
MostDerived* md2 = dynamic_cast<MostDerived*>(b2); // This is safe
md1->print(); // Prints "MostDerived"
md2->print(); // Prints "MostDerived"
return 0;
}
Cette section couvre les sujets suivants :