2016-05-30 14 views
1

Ich habe zwei Klassen, Base und Derived. Ich habe einen Container, der eine Liste von Derived* Zeigern speichert.Wie kann ich Base * gegen eine Liste von Derived * innerhalb von Base destructor anpassen?

Es ist ein Signal/Schlitz-Mechanismus, der ein Signal aussendet, wenn ein Basisobjekt zerstört wird, und an diesem Punkt sind wir in ~Base destructor, so RTTI für Base* zu Derived* Umwandlung nicht verfügbar ist (dieses Qt verwendet, aber die Frage ist nicht Qt spezifisch)

Dieses Signal ist mit einem Steckplatz verbunden, der den Pointer-Container verwaltet. Wie Sie vielleicht erraten haben, möchte ich überprüfen, ob der Zeiger Base*, dessen Objekt zerstört wird, einem im Container gespeicherten Zeiger Derived* entspricht, und wenn ja, entfernen Sie ihn aus dem Container.

Ich weiß, dass es viele alternative Designs gibt, wie zum Beispiel das Signal QObject::destroyed() nicht verwenden oder eine Liste von QObject* statt Derived* speichern. Aber ich möchte das aus vielen praktischen Gründen verwenden.

Das bedeutet, ich möchte einen Basiszeiger auf einen abgeleiteten Zeiger, nicht zur Dereferenzierung, sondern zum Aufspüren des Zeigers konvertieren, und ich will, dass es definiert wird, was auch immer der Unterklassenbaum ist (einschließlich Mehrfachvererbung, virtuelle Funktionen). ..).

Kann ich static_cast dafür verwenden?

Danke!

+0

Oops - Dank für bemerken – galinette

+0

Nun können Sie eine 'static_cast' verwenden, aber Sie müssen sein sicher, den richtigen Typ zu haben. –

+0

@DavidHaim: Wie gesagt, ich weiß, es gibt andere mögliche Designs, aber die Frage ist hier spezifisch. Ich kann die Base-Klasse hier nicht ändern (das ist die QObject Qt-Basisklasse) – galinette

Antwort

3

Sie können static_cast für den Typ base für jedes Element Ihres Containers verwenden und vergleichen Sie es mit Ihrem *base ptr. So finden Sie das Objekt.

class Base; 
class Derived; 
std::vector<Derived*> arrDerived; 

void Remove(Base* pBase); 

class Base 
{ 
public: 
    ~Base() 
    { 
     Remove(this); 
    } 
}; 

class Derived : public Base 
{ 

}; 

void Remove(Base* pBase) 
{ 
    for (Derived* pDerived : arrDerived) 
    { 
     //if (static_cast<Base*>(pDerived) == pBase) same as 
     if (pDerived == pBase) 
     { 
      //you found it!!!! 
      return; 
     } 
    } 
} 

Wenn Sie das tun static_cast<Base*>(Derived) Compiler bewegt sich nur ptr von einigen const Speichermenge niedriger (so verweist er auf die Basisklasse). Daher ist diese Operation unabhängig vom aktuellen Speicherstatus und safe für Sie.

Edit: als @alain erwähnt können Sie ohne static_cast vergleichen - es wird automatisch durchgeführt werden.

+0

Danke für die Antwort In welchen Fällen würde das Gegenteil (Upcasting des ptr) ein undefiniertes Verhalten sein? – galinette

+0

Ich habe die Antwort editiert.Upcasting wird auch funktionieren, wenn Sie alle Objekte zerstören :) Die Sache ist, was "Upcasting" von "ungültiger Zeiger" wird ungültig geben Zeiger ". Aber für die Suche wird es nicht metter. –

4

In einem Kommentar, Sie schrieb:

der gegossenen Zeiger auf eine Tabelle zum Entfernen von es * Zeiger Abgeleitet verglichen wird. Natürlich werde ich den Zauberzeiger nicht dereferenzieren.

In diesem Fall wird keine Besetzung überhaupt benötigt, können Sie Ihre Zeiger direkt vergleichen kann:

Base* base; 
Derived* derived; 
if(base == derived) { 
} 
+0

Das macht Sinn. 'static_cast' wird automatisch ausgeführt. –