Ce face operatorul dynamic_cast?
Raspuns
Operatorul dynamic_cast<type>(expr) converteste tipul expresiei expr la (face cast la) tipul type, unde:
- type este pointer sau referinta la un tip clasa sau pointer la void;
- daca type este tip pointer, expr este pointer la un tip clasa;
- daca type este tip referinta, expr este un tip clasa.
Code: Select all
CFoo foo;
CBar rBar = dynamic_cast<CBar&>(foo);
CBar* pBar = dynamic_cast<CBar*>(&foo);
void* p = dynamic_cast<void*>(&foo);
Exceptand cazul in care type este void*, conversia este corecta daca cel mai derivat obiect din expr pointeaza (refera) la un sub-obiect public de tipul type in mod ne-ambiguu.
Un pic mai clar, in exemplele urmatoare:
Exemplu [2]
Code: Select all
class A {virtual void f() {}};
int main()
{
A* pA = new A;
void* p = dynamic_cast<void*>(pA); // OK, void* can point to anyting
// ...
}
Code: Select all
class A {virtual void f() {}};
class B : public A {};
class C : public A {};
class D : public B {};
int main()
{
A* pA = new D;
// most derived object pointed by pA is of type 'class D'
// pA also unambiguously points to public sub-objects of
// type 'class B' and type 'class A'.
D* pD = dynamic_cast<D*>(pA); // run-time test succeeds
B* pB = dynamic_cast<B*>(pA); // run-time test succeeds
const A* pA2 = dynamic_cast<const A*>(pA); // run-time test succeeds
// ...
}
Code: Select all
class A {virtual void f() {}};
class B {virtual void f() {}};
int main()
{
B b;
// 'class A' and 'class B' are unrelated classes,
// then 'b' does not refer to a sub-object of type 'class A'.
A& rA = dynamic_cast<A&>(b); // run-time test fails
// ...
}
Code: Select all
class A {virtual void f() {}};
class B : public A {};
class C : public A {};
class D : public B {};
int main()
{
B* pB = new B;
// pB does not point to a sub-object of type 'class C'.
C* pC = dynamic_cast<C*>(pB); // run-time test fails
// pB does not point to a sub-object of type 'class D'.
D* pD = dynamic_cast<D*>(pB); // run-time test fails
// ...
}
Code: Select all
class A {virtual void f() {}};
class B : protected A {};
int main()
{
B b;
// b refers to a sub-object of type 'class A' which is not public.
A& rA = dynamic_cast<A&>(b); // Inaccessible base; run-time test fails
// ...
}
Code: Select all
class A { virtual void f() {} };
class B : public A {};
class C : public A {};
class D : public B, public C {};
int main()
{
D* pD = new D;
// pD points to a public sub-object of type 'class A'
// which is not unique because of multiple non-virtual inheritance.
A* pA = dynamic_cast<A*>(pD); // Ambiguous base; run-time test fails
// ...
}
- ...daca s-a facut cast la un pointer, valoarea returnata este pointerul NULL;
Exemplu [8]Code: Select all
B* pB = dynamic_cast<B*>(pA); if(NULL == pB) { // run-time test failed }
- ...daca s-a facut cast o referinta, atunci se arunca o exceptie tip bad_cast.
Exemplu [9]Code: Select all
try { A& rA = dynamic_cast<A&>(b); } catch(std::bad_cast& e) { // run-time test failed std::cout << e.what() << std::endl; }
Note
- Pentru ca operatorul dynamic_cast face verificari la run-time, se poate zice ca este inclus in mecanismul RTTI (Run-Time Type Identification).
Exemplu [10]Code: Select all
class A {virtual void f() = 0;}; class B : public A {virtual void f() {}}; class C : public A {virtual void f() {}}; class D : public A {virtual void f() {}}; void some_function(A* pA) { if(NULL == dynamic_cast<B*>(pA)) { // pA points to a 'class B' object } else if(NULL == dynamic_cast<C*>(pA)) { // pA points to a 'class C' object } else if(NULL == dynamic_cast<D*>(pA)) { // pA points to a 'class D' object } }
- Pentru a putea face conversii intre clase folosind dynamic_cast, clasele trebuie sa fie polimorfice, adica sa contina functii virtuale. Alfel, compilatorul semnaleaza o eroare.
Exemplu [11]Code: Select all
class A {/* no virtual functions */}; class B : public A {}; int main() { A* pA = new B; B* pB = dynamic_cast<B*>(pA); // Compiler error. dynamic_cast: 'A' is not a polymorphic type // ... }
- Printre programatorii C++ si prin diverse manuale/tutoriale este raspandita afirmatia "dynamic_cast nu eşuează niciodată atunci când convertim o clasă în clasa de bază". Exemplele [6] si [7] dovedesc contrariul.
- Acest articol este "under construction" iar pe parcurs poate sa sufere modificari si adaugiri. Daca descoperiti greseli, omisiuni sau neclaritati, va rog sa deschideti un topic in forumul de discutii "Limbajul C++".
- ISO/IEC 14882:2003 - 5.2.7 Dynamic cast
- [MSDN] dynamic_cast Operator
<< Back to C++ Index