dynamic_cast
conversion
Convertit de manière sécurisée les pointeurs et références vers des classes vers le haut, vers le bas et latéralement le long de la hiérarchie d'héritage.
Table des matières |
Syntaxe
dynamic_cast<
type-cible
>(
expression
)
|
|||||||||
| target-type | - | pointeur vers un type de classe complet, référence vers un type de classe complet, ou pointeur vers void (éventuellement qualifié cv) |
| expression | - | lvalue (jusqu'à C++11) glvalue (depuis C++11) d'un type de classe complet si target-type est une référence, prvalue d'un pointeur vers un type de classe complet si target-type est un pointeur |
Explication
Pour faciliter la description, «
expression
ou le résultat est une référence à
T
» signifie que « c'est une glvalue de type
T
»
, ce qui suit la convention de
decltype
(depuis C++11)
.
Seules les conversions suivantes peuvent être effectuées avec dynamic_cast , sauf lorsque ces conversions supprimeraient la constance (ou la volatilité).
Base
» et que le type de
expression
est « pointeur vers (éventuellement qualifié cv)
Derived
» tel que
Base
est une classe de base de
Derived
, le résultat est
- une valeur de pointeur nul si expression est une valeur de pointeur nul, ou
-
un pointeur vers le
Basesous-objet unique de l'objetDerivedpointé par expression sinon. En d'autres termes, dynamic_cast peut être utilisé pour effectuer un upcast de pointeurs, de la classe dérivée vers la classe de base. Une conversion implicite et static_cast peuvent également effectuer cette conversion.
Base
» et que le type de
expression
est « (éventuellement qualifié cv)
Derived
» tel que
Base
est une classe de base de
Derived
, le résultat est le sous-objet
Base
unique de l'objet
Derived
désigné par
expression
. Autrement dit,
dynamic_cast
peut être utilisé pour effectuer un
upcast
de références, de la classe dérivée vers la classe de base. Une conversion implicite et
static_cast
peuvent également réaliser cette conversion.
Target
, pointé ou référencé par
target-type
:
Target
, et si un seul objet de type
Target
est dérivé du sous-objet pointé/référé par
expression
, le résultat pointe/se réfère à cet objet
Target
. En d'autres termes,
dynamic_cast
peut être utilisé pour effectuer un
downcast
de pointeurs/références, de la base vers la dérivée.
Target
, le résultat pointe/réfère au sous-objet
Target
de l'objet le plus dérivé. Autrement dit,
dynamic_cast
peut être utilisé pour effectuer un
crosscast
(ou side-cast) des pointeurs/références, entre deux types dérivés de la même base.
- Si target-type est un type pointeur, le résultat est la valeur de pointeur nul de target-type .
- Si target-type est un type référence, une exception d'un type qui correspondrait à un gestionnaire de type std::bad_cast est levée.
Lorsque dynamic_cast est utilisé dans un constructeur ou un destructeur (directement ou indirectement), et que expression fait référence à l'objet actuellement en cours de construction/destruction, l'objet est considéré comme l'objet le plus dérivé. Si target-type n'est pas un pointeur ou une référence vers la propre classe du constructeur/destructeur ou l'une de ses bases, le comportement est indéfini.
Similaire à d'autres expressions de cast, le résultat est :
|
(jusqu'à C++11) |
|
(depuis C++11) |
Notes
Un downcast peut également être effectué avec
static_cast
, ce qui évite le coût de la vérification à l'exécution, mais cela n'est sûr que si le programme peut garantir (par une autre logique) que l'objet pointé par
expression
est définitivement
Derived
.
Certaines formes de dynamic_cast reposent sur l' identification du type à l'exécution (RTTI), c'est-à-dire des informations sur chaque classe polymorphe dans le programme compilé. Les compilateurs disposent généralement d'options pour désactiver l'inclusion de ces informations.
Mots-clés
Exemple
#include <iostream> struct V { virtual void f() {} // doit être polymorphe pour utiliser dynamic_cast vérifié à l'exécution }; struct A : virtual V {}; struct B : virtual V { B(V* v, A* a) { // casts pendant la construction (voir l'appel dans le constructeur de D ci-dessous) dynamic_cast<B*>(v); // bien défini : v de type V*, V base de B, donne B* dynamic_cast<B*>(a); // comportement indéfini : a a le type A*, A n'est pas une base de B } }; struct D : A, B { D() : B(static_cast<A*>(this), this) {} }; struct Base { virtual ~Base() {} }; struct Derived : Base { virtual void name() {} }; int main() { D d; // l'objet le plus dérivé A& a = d; // upcast, dynamic_cast peut être utilisé, mais inutile [[maybe_unused]] D& new_d = dynamic_cast<D&>(a); // downcast [[maybe_unused]] B& new_b = dynamic_cast<B&>(a); // sidecast Base* b1 = new Base; if (Derived* d = dynamic_cast<Derived*>(b1); d != nullptr) { std::cout << "downcast from b1 to d successful\n"; d->name(); // sûr d'appeler } Base* b2 = new Derived; if (Derived* d = dynamic_cast<Derived*>(b2); d != nullptr) { std::cout << "downcast from b2 to d successful\n"; d->name(); // sûr d'appeler } delete b1; delete b2; }
Sortie :
downcast from b2 to d successful
Rapports de défauts
Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.
| DR | Appliqué à | Comportement publié | Comportement corrigé |
|---|---|---|---|
| CWG 1269 | C++11 |
la vérification à l'exécution n'était pas effectuée pour les
expression s xvalue si target-type est un type de référence rvalue |
effectuée |
| CWG 2861 | C++98 | expression pouvait pointer/référencer un objet inaccessible par le type | le comportement est indéfini dans ce cas |
Références
- Norme C++23 (ISO/IEC 14882:2024) :
-
- 7.6.1.7 Dynamic cast [expr.dynamic.cast]
- Norme C++20 (ISO/CEI 14882:2020) :
-
- 7.6.1.6 Conversion dynamique [expr.dynamic.cast]
- Norme C++17 (ISO/IEC 14882:2017) :
-
- 8.2.7 Conversion dynamique [expr.dynamic.cast]
- Norme C++14 (ISO/IEC 14882:2014) :
-
- 5.2.7 Conversion dynamique [expr.dynamic.cast]
- Norme C++11 (ISO/CEI 14882:2011) :
-
- 5.2.7 Conversion dynamique [expr.dynamic.cast]
- Norme C++98 (ISO/CEI 14882:1998) :
-
- 5.2.7 Conversion dynamique [expr.dynamic.cast]
- Norme C++03 (ISO/IEC 14882:2003) :
-
- 5.2.7 Dynamic cast [expr.dynamic.cast]