Kann ich warf std::vector<Tier*> std::vector<Hund*> ohne Blick auf jedes element?
Ich habe eine base-Klasse mit mehreren Klassen erweitert werden. Ich habe einige generische Bibliothek Dienstprogramme, erstellt einen Vektor mit Zeigern auf die Basisklasse, so dass jede der Unterklassen funktioniert. Wie kann ich warf alle Elemente des Vektors um einen bestimmten untergeordneten Klasse?
//A method is called that assumes that a vector containing
//Dogs casted to Animal is passed.
void myDogCallback(vector<Animal*> &animals) {
//I want to cast all of the elements of animals to
//be dogs.
vector<Dog*> dogs = castAsDogs(animals);
}
Meine naive Lösung würde wie folgt Aussehen:
//A method is called that assumes that a vector containing
//Dogs casted to Animal is passed.
void myDogCallback(vector<Animal*> &animals) {
//I want to cast all of the elements of animals to
//be dogs.
vector<Dog*> dogs;
vector<Animal*>::iterator iter;
for ( iter = animals.begin(); iter != animals.end(); ++iter ) {
dogs.push_back(dynamic_cast<Dog*>(*iter));
}
}
- Duplizieren: stackoverflow.com/questions/902667/...
- Es ist nicht ganz dupe - Hinweis, dass er nicht das kopieren von
vector<Derived*>
zuvector<Base*>
, aber anders herum! - Ich denke, er ist auf der Suche für eine automatische / implizite niedergeschlagen!
- Hm, stimmt. :X
- Vielen Dank für das feedback. 🙂 War nicht sicher, wie Sie Sie zu Fragen, dies und ja, hatte eine harte Zeit zu wissen, was Sie suchen!
Du musst angemeldet sein, um einen Kommentar abzugeben.
Könnten Sie
std::transform
. Es verwendet immer nochfor()
intern, aber man bekommt zwei-string Umsetzung:Ihrem code, wie geschrieben, wird eine Reihe von null-Zeiger in Ihre Hunde-Vektor, wenn die Tiere Vektor enthält andere Tier-Spezialisierungen.
Gibt es zwei Möglichkeiten. Die einfachste ist die Verwendung von so etwas wie
remove_copy_if
. Ich kann nicht erklären, warum Sie nennen es das, aber es kopiert die Elemente von einem container zum anderen, dass nicht, die das Prädikat erfüllen. Hier ist die grundlegende Idee (ungetestet):}
Glaube ich, ein Weg, um zu schauen
remove_copy_if
ist, zu denken, es alscopy_unless
.Einen alternativen Ansatz, wenn Sie die Basis Ihres Codes um Iteratoren nur, umwickelt Sie den iterator für den vector < Tier* > mit einem, gibt nur die Hunde aus der Sammlung. Der entscheidende Vorteil hier ist, dass Sie immer noch nur ein container, aber natürlich ist Sie ein wenig mehr bezahlen, da Sie den Algorithmus für die Navigation über die gesamte Sammlung von Tieren.
Dies ist sehr rau, aber ich hoffe es zeigt das grundlegende Prinzip.
In der Regel ist es nicht sehr gut zu verwenden dynamic_cast für downcasting. Sie sollte wohl umgestalten von code, so dass Sie nicht brauchen, um verwenden Sie die explizite downcasting.
Sehen CPP FAQ lite für einige weitere Informationen.
UPD Auch, siehe Stroustrup Seite (suchen Sie nach "Warum kann ich nicht zuordnen, einen Vektor zu einem Vektor?")
Wenn Sie sagen, dass Sie garantieren können, dass jedes element ist wirklich ein Hund dann nur
static_cast
d.h.Ich in der Regel immer eine Kurzschlussreaktion von Menschen, das ist schlecht und man sollte immer
dynamic_cast
aber in Wirklichkeit, wenn Sie können, machen Sie garantiert über die Art dann ist es vollkommen sicher und IMO eine sinnvolle Sache zu tun.Auch die Garantie würde bedeuten, dass der neue Vektor hat dieselbe Größe reservieren Sie also den gleichen Raum zu vermeiden, tun alle Zuordnungen, die in jedem
push_back
. Als alternative Schleife, die ich verwendet habe, einen index nur, weil ich immer denke, dass die Iteration mit index müssen schneller sein als ein iterator aber das ist ja wohl Quatsch 🙂Wenn man sicherstellen kann, dass Ihre
std::vector<Animal*>
enthält nurDog*
können Siereinterpret_cast
.Mischen der
std::transform
Methodik mit einemstatic_cast
(weil Sie sich sicher sind, dass seine Sicherheit) könnte wie folgt Aussehen: