5 Stimmen

Vector-Iteratoren umwandeln

Hallo, In C++, ich habe einen Vektor vom Typ:

vector myVector;

in den ich Zeiger von abgeleiteten Klassen einfüge (push_back).

Jetzt möchte ich die Elemente wieder aus dem Vektor entfernen, also mache ich das:

vector::iterator iter;

for (iter = myVector.rbegin(); iter != myVector.rend(); iter++)
{
 // aber bevor ich es entferne, muss ich es herunterfahren
 // deshalb führe ich diesen Cast durch
 // aber so kann ich die Funktion nicht aufrufen
 (DerivedClass*(*iter))->Shutdown();

 myVector.pop_back();
}

aber wie bereits in den Kommentaren erwähnt, muss ich vor dem Entfernen die Methode Shutdown() aufrufen und der Cast funktioniert auch nicht richtig. Gibt es Lösungsansätze? oder ist es unmöglich?

13voto

sbi Punkte 211669
while (!myVector.empty())
{
  ((DerivedClass*)(myVector.back()))->Shutdown();
  myVector.pop_back();
}

Notizen:

  • Sie sollten wahrscheinlich dynamic_cast anstelle des harten Casts verwenden. (Wenn sicher ist, dass es nur DerivedClass-Objekte im Vektor gibt, warum ist es dann nicht std::vector?)
  • Sie sollten wahrscheinlich überhaupt nicht casten müssen, da Shutdown() in der Basisklasse deklariert sein sollte.
  • Sie sollten wahrscheinlich die Objekte auch löschen, bevor Sie sie aus dem Vektor entfernen. (Das muss aber nicht so sein.)
  • Sie sollten wahrscheinlich einen Smart Pointer verwenden, der Shutdown() aufruft (und wahrscheinlich auch delete).

Bearbeiten: Die Verwendung von std::vector::clear(), wie von markh44 gezeigt, ist wahrscheinlich besser als das pop_back().

2voto

markh44 Punkte 5498

Könnten Sie Shutdown in BaseClass zu einer virtuellen Funktion machen? Dann bräuchten Sie keinen Cast.

Außerdem werden Sie wahrscheinlich Probleme haben, Elemente aus einem Vektor während der Iteration zu entfernen. Ich würde es so machen:

vector::iterator iter;

for (iter = myVector.rbegin(); iter != myVector.rend(); iter++)
{
    (*iter)->Shutdown();
}
myVector.clear();

Bearbeitung: Und noch etwas, ++iter wird im Allgemeinen gegenüber iter++ bevorzugt.

1voto

stefaanv Punkte 13390

Der Konstruktor-Casting funktioniert nicht für Zeiger. Verwenden Sie static_cast, wenn Sie sicher sind, oder dynamic_cast und überprüfen Sie.

-1voto

davidnr Punkte 3385

Wenn Shutdown() eine virtuelle Methode der Basisklasse ist, d.h. BaseClass::ShutDown(), sollten Sie direkt iter->ShutDown(); aufrufen.

Andernfalls, wenn die Methode nicht virtual ist, sollten Sie dynamic_cast verwenden.

vector::iterator iter;

for (iter = myVector.rbegin(); iter != myVector.end(); iter++)
{
    DerivedClassA* a = dynamic_cast(*iter);
    if (a) a->ShutDownA();
    else
    {
        DerivedClassB* b = dynamic_cast(*iter);
        if (b) b->ShutDownB();
        // ... für jede Klasse in der Hierarchie, die im Vektor sein könnte, wiederholen.
    }
    myVector.pop_back();
}

Auf jeden Fall vermutlich haben Sie einen Speicherleck, es sei denn, ShutDown() löscht das Objekt selbst (was im Allgemeinen keine gute Idee ist) oder Sie halten duplizierte Zeiger und löschen sie an anderer Stelle, was eine andere riskante Idee ist.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X