Dynamic_cast

I programmeringssproget C ++ er operatøren dynamic_castmedlem af RTTI-systemet ( run-time type information ), der udfører typekonvertering . Men i modsætning til det rollebesætning, der er arvet fra C-sproget, udføres en typekontrol ved kørsel og kaster enten en undtagelse i tilfælde af referencer eller en nul-markør i tilfælde af markører, hvis typerne ikke er kompatible. Så dynamic_castopfører sig mere som en typekonverter på et sprog som Java snarere end en konvertering i betydningen C-sprog, som ikke kontrollerer noget ved kørsel.

Prøvekode

Lad være en klasse A, arvet af B. Antag at en metode tager et objekt af typen som Aet argument, som vil udføre yderligere behandling, hvis objektet faktisk er en forekomst af typen B. Dette kan opnås ved hjælp dynamic_castaf følgende:

#include <typeinfo> // Pour std::bad_cast #include <iostream> // Pour std::cerr, etc. class A { public: // Puisque RTTI est incluse dans la table des méthodes virtuelles (la vtable), // il devrait y avoir au moins une fonction virtuelle pure. virtual void foo() = 0; // autres membres... }; class B : public A { public: void foo() { /* ... */ } void methodSpecificToB() { /* ... */ } // autres membres... }; void my_function(A& my_a) { try { B& my_b = dynamic_cast<B&>(my_a); my_b.methodSpecificToB(); } catch (const std::bad_cast& e) { std::cerr << e.what() << std::endl; std::cerr << "Cet objet n'est pas de type B" << std::endl; } }

En ækvivalent version af my_functionkan skrives ved hjælp af markører i stedet for referencer:

void my_function(A* my_a) { B* my_b = dynamic_cast<B*>(my_a); if (my_b != nullptr) my_b->methodSpecificToB(); else std::cerr << "Cet objet n'est pas de type B" << std::endl; }

Implementering

For at forstå, hvordan det fungerer, kan vi se på, hvordan dynamic_cast kan implementeres manuelt.

#include <iostream> // Pour std::cerr, etc. class B; class C; class A { /// la méthode qui permettra de connaitre le type complet de notre objet virtual const char get_type_for_dynamic_cast() const = 0; public: B* dynamic_cast_to_B() { if (get_type_for_dynamic_cast() != 'B') return 0; return static_cast<B*>(this); } C* dynamic_cast_to_C() { if (get_type_for_dynamic_cast() != 'C') return 0; return static_cast<C*>(this); } }; class B : public A { int data; const char get_type_for_dynamic_cast() const { return 'B'; } public: B(int data) : data(data) { } void methode() { std::cout << data << "\n"; } }; class C : public A { char* data; const char get_type_for_dynamic_cast() const { return 'C'; } public: C(char* data) : data(data) { } void methode() { std::cout << data << "\n"; } }; void ma_fonction(A* a) { if (B* b = a->dynamic_cast_to_B()) b->methode(); else if (C* c = a->dynamic_cast_to_C()) c->methode(); else { // erreur de type } }

Vi ser, at i vores hukommelse, hvis vores klasser allerede har en VTable , er prisen næsten nul, da vi lige har tilføjet en metode i VTable for hver klasse. Med hensyn til beregningstid forbliver omkostningerne ret lave: en normal rollebesætning kræver ikke nogen beregning, mens vi her skal kalde en ren virtuel metode (hvis adresse skal læses i VT-tabellen ) og undersøge dens returværdi.

Se også

Relaterede artikler

eksterne links