Ich habe eine Basisklasse mit mehreren Klassen, die sie erweitern. Ich habe einige generische Bibliotheksprogramme, die einen Vektor erstellen, der Zeiger auf die Basisklasse enthält, so dass jede der Unterklassen funktioniert. Wie kann ich alle Elemente des Vektors in eine bestimmte Kindklasse umwandeln?
%Vor%Meine naive Lösung würde etwa so aussehen:
%Vor% Sie könnten std::transform
verwenden. Es verwendet intern for()
, aber Sie erhalten eine Implementierung mit zwei Zeichenfolgen:
Es gibt zwei Möglichkeiten. Am einfachsten ist es, etwas wie remove_copy_if
zu verwenden. Ich kann nicht erklären, warum sie es so nennen, aber es kopiert die Elemente von einem Container in einen anderen, die das Prädikat nicht erfüllen. Hier ist die Grundidee (ungetestet):
}
Ich denke, eine Möglichkeit, remove_copy_if
zu betrachten, ist, sie als copy_unless
zu betrachten.
Ein alternativer Ansatz besteht darin, den Iterator für den Vektor & lt; zu umbrechen, wenn Sie Ihren Code nur auf Iteratoren aufbauen. Tier * & gt; mit einem, der nur die Hunde aus der Sammlung zurückgibt. Der Hauptvorteil hier ist, dass Sie immer noch nur einen Container haben, aber natürlich zahlen Sie ein bisschen mehr, da Ihr Algorithmus über die gesamte Sammlung von Tieren navigieren wird.
%Vor%Das ist sehr grob, aber ich hoffe, es zeigt Ihnen das Grundprinzip.
Normalerweise ist es nicht gut, dynamic_cast für Downcasting zu verwenden. Sie sollten Ihren Code wahrscheinlich umgestalten, damit Sie keine expliziten Downcasts verwenden müssen.
Weitere Informationen finden Sie CPP FAQ lite .
UPD Siehe auch Stroustrup-Seite (suchen Sie nach "Warum? kann ich einem Vektor keinen Vektor zuordnen? ")
Wenn Sie sagen, dass Sie garantieren können, dass jedes Element wirklich ein Hund ist, dann geben Sie einfach static_cast
i.d.
Ich bekomme normalerweise immer eine reflexartige Reaktion von Leuten, dass das schlecht ist und du solltest immer dynamic_cast
verwenden, aber in der Realität, wenn du Garantien über den Typ machen kannst, ist es vollkommen sicher und IMO eine vernünftige Sache .
Außerdem würde Ihre Garantie bedeuten, dass der neue Vektor die gleiche Größe hat, also reservieren Sie den gleichen Platz, um Zuweisungen in jedem push_back
zu vermeiden. Als eine alternative Schleife habe ich einen Index verwendet, nur weil ich immer daran denke, dass das Iterieren mit einem Index schneller sein muss als ein Iterator, aber das ist wahrscheinlich Unsinn:)
Wenn Sie sicherstellen können, dass Ihr std::vector<Animal*>
nur Dog*
enthält, können Sie reinterpret_cast
verwenden.