2013-04-09 19 views
14

Sagen wir, wir haben eine Klassenhierarchie. Am unteren Ende haben wir Basis und oben Abgeleitet. So ermitteln Sie die Objektklasse, selbst wenn sie in den Basisklassenzeiger konvertiert wird.So ermitteln Sie den tatsächlichen Objekttyp zur Laufzeit in C++;

Base* b = new Derived(): 

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

Gibt es eine andere Möglichkeit als manuelle Implementierung von String-Feld oder solche und virtuelle Get-Funktion?

PS: Ich spreche von Compiler-unabhängige Lösung

+3

Dies ist möglich, wie in der Antwort erklärt, aber das ist fast immer eine falsche Sache zu tun. Was versuchst du hier zu erreichen? –

+0

Nichts genau es ist nur für den Zweck der Argumentation :) – user1079475

+1

Mehr anwendungsorientierte Version: http://stackoverflow.com/questions/351845/finding-the-type-of-an-object-in-c || Generische Version, die Vererbung nicht erwähnt: http://stackoverflow.com/questions/11310898/how-do-i-get-the-type-of-a-variable –

Antwort

26

sicherstellen, dass die Basisklasse mindestens eine virtuelle Methode ist, umfassen <typeinfo> und Ihren aktuellen Code verwenden, nur mit einem zusätzlichen Dereferenzierung, typeid(*b).name().


nebenbei beachten Sie, dass ein typeid Aufruf der in C ein Ort ist ++, wo man dereferenzieren einen Nullpointer mit gut definierten Verhalten, das, dass es bedeutet, eine Ausnahme auslösen kann:

C++ 11 § 5.2.8/2:
“ Wenn der glvalue Ausdruck durch Anwenden des unären * Operator auf einen Zeiger und der Zeiger ist ein Nullzeiger-Wert (4,10) erhalten wird, die typeid Expression führt die std::bad_typeid Ausnahme (18.7.3) . ”

+4

Es ist eine gute Idee, Destruktor als "at mindestens eine virtuelle Methode " –

8

Wenn alles, was Sie tun möchten, ist zu finden, wenn b tatsächlich Derived Punkte, nur dynamic_cast() verwenden:

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

dynamic_cast gibt einen Null-Zeiger, wenn der tatsächliche Laufzeittyp des Objekts zu spitz durch b ist nicht Derived (oder eine von Derived abgeleitete Klasse). Im Gegensatz zu dem name() Mitglied von std::type_info ist dies compilerinvariant.

Beachten Sie, dass dies nur funktioniert, wenn Base mindestens ein virtuelles Element Funktionen hat. Was auch immer es tun sollte, da Sie Typen manipulieren, die von ihm über einen Basiszeiger abgeleitet werden, also sollte es einen virtuellen Destruktor haben.

+0

Aber der Fall ist, dass ich nicht Code modyf jederzeit ändern möchte ich neue Klasse hinzufügen. – user1079475