2013-04-21 31 views
7

Angenommen, ich habe eine abstrakte Basisklasse Parent und Unterklassen Child1 und Child2. Wenn ich eine Funktion habe, die ein Parent * verwendet, gibt es einen Weg (vielleicht mit RTTI?), Um zur Laufzeit festzustellen, ob es ein Child1 * oder ein Child2 * ist, das die Funktion tatsächlich empfangen hat?Identifizieren einer Unterklasse mit einem Zeiger auf ihre Basisklasse?

Meine bisherige Erfahrung mit RTTI ist, dass, wenn foo ein Parent * ist, typeid (foo) typeid (Parent *) zurückgibt, unabhängig von der Kindklasse, zu der foo gehört.

+2

Ein 'Parent *' ist immer ein 'Parent *'. Es ist * nie * ein 'Kind *'. Was Sie fragen wollen, ist "was ist die Art der Sache, auf die es zeigt". –

+0

Kerrek SB: Ich habe dir gestern die kalte Schulter gegeben, aber als ich zur eigentlichen Programmierung kam, war dein Kommentar wahrscheinlich wertvoller als alles andere auf der Seite. Entschuldigung, dass ... – ExOttoyuhr

Antwort

5

Sie müssen an der typeid des dereferenzierten Zeiger suchen, nicht der Zeiger selbst; Das heißt, typeid (* foo), nicht typeid (foo). Wenn Sie nach dem dereferenzierten Zeiger fragen, erhalten Sie den dynamischen Typ. Wenn Sie nach dem Zeiger selbst fragen, erhalten Sie nur den statischen Typ, wie Sie beobachten.

+0

Das klingt nach einer genaueren Übereinstimmung mit dem, wonach ich gesucht habe, als das Erstellen zahlreicher Unterklassenzeiger wäre ... – ExOttoyuhr

+0

Es ist erwähnenswert, dass 'typeid (* foo)' nur den korrekten Laufzeittyp (dh ' Child1' anstelle von 'Parent'), wenn die Elternklasse mindestens eine virtuelle Methode besitzt. – ApproachingDarknessFish

2

Sure:

BaseClass *bptr = // whatever, pointer to base class 
SubclassOne *safe_ptr_one = dynamic_cast<SubclassOne *>(bptr); 
if (safe_ptr_one != nullptr) { 
    // Instance of SubclassOne 
} else { 
    // not an instance of SubclassOne, try the other one 
    SubclassTwo *safe_ptr_two = dynamic_cast<SubclassTwo *>(bptr); 
    if (safe_ptr_two != nullptr) { 
     // Instance of SubclassTwo 
    } else { 
     // it wasn't either one :'(
    } 
} 
+0

Nice - Ich wusste nicht, dynamic_cast könnte das tun! (Aber dann, darum habe ich gefragt.) – ExOttoyuhr

+0

@ExOttoyuhr Gern geschehen. Und yay, ich habe es geschafft, eine Antwort vor Andy Prowl zu geben! –

5

Sie std::dynamic_cast dafür verwenden können.

Parent* ptr = new Child1(); 
if(dynamic_cast<Child1*>(ptr) != nullptr) { 
    // ptr is object of Child1 class 
} else if(dynamic_cast<Child2*>(ptr) != nullptr) { 
    // ptr is object of Child2 class 
} 

Auch wenn Sie intelligente Zeiger verwenden, wie std::shared_ptr, können Sie es wie folgt kontrollieren:

std::shared_ptr<Parent> ptr(new Child1()); 
if(std::dynamic_pointer_cast<Child1>(ptr) != nullptr) { 
    // ptr is object of Child1 class 
} else if(std::dynamic_pointer_cast<Child2>(ptr) != nullptr) { 
    // ptr is object of Child2 class 
}