2013-04-09 20 views
14

Powiedzmy, że mamy hierarchię klas. Na dole mamy Base i u góry Derived. Jak określić klasę obiektu, nawet jeśli jest konwertowana na wskaźnik klasy bazowej.Jak określić rzeczywisty typ obiektu w środowisku wykonawczym w C++;

Base* b = new Derived(): 

typeid(b).name(); // i want this to tell me that this is actually derived not base object 

Czy istnieje sposób inny niż ręczna implementacja pola ciąg lub taka i wirtualna funkcja get?

PS: I mówisz kompilator niezależne rozwiązanie

+3

Jest to możliwe, jak wyjaśniono w odpowiedzi, ale prawie zawsze jest to niewłaściwe. Co próbujesz osiągnąć tutaj? –

+0

Nic dokładnie nie jest po to, aby się spierać :) – user1079475

+1

Więcej wersji aplikacji: http://stackoverflow.com/questions/351845/finding-the-type-of-an-object-in-c || Bardziej ogólna wersja, która nie wspomina o dziedziczeniu: http://stackoverflow.com/questions/11310898/how-do-i-get-the-type-of-a-variable –

Odpowiedz

26

upewnić się, że klasa bazowa posiada co najmniej jedną metodę wirtualną, to <typeinfo> i użyć aktualnego kodu tylko z dodatkowym dereferencing, typeid(*b).name().


mimochodem, trzeba pamiętać, że typeid połączenie jest jedynym miejscem, w C++, gdzie można dereference w NullPointer z dobrze zdefiniowanym zachowania, co oznacza, że ​​może rzucić wyjątek:

C++ 11 § 5.2.8/2:
“ Jeżeli glvalue ekspresję uzyskuje się przez zastosowanie jednoargumentowy * operatora do wskaźnika i wskaźnika jest zerowa wartość wskaźnika (4,10), przy czym ekspresja typeid zgłasza wyjątek std::bad_typeid (18.7.3) . ”

+4

Dobrym pomysłem jest mieć destruktor jako "w najmniej jedna wirtualna metoda " –

8

Jeśli wszystko, co chcesz zrobić, to znaleźć, jeśli b faktycznie wskazuje na Derived, wystarczy użyć dynamic_cast():

if (dynamic_cast<Derived*>(b)) { ... } 

dynamic_cast zwraca zerowy wskaźnik, jeśli rzeczywisty typ wykonawcze obiektu wskazywanego przez b nie jest Derived (lub klasa pochodna od Derived). W przeciwieństwie do elementu name() z std::type_info, jest to niezmienna kompilator.

Należy zauważyć, że działa to tylko wtedy, gdy funkcja Base ma co najmniej jeden element wirtualny. I tak powinno być, ponieważ manipuluje się typami pochodnymi od niego przez wskaźnik bazowy, więc powinien mieć wirtualny destruktor.

+0

Ale tak jest, że nie chcę modyfikować kodu za każdym razem, gdy dodaję nową klasę. – user1079475