Iteratur Liste
-
Hey Leute,
ganz kurze Frage...warum muss man, wenn man eine Liste bestehend aus Zeigern auf Objekte hat, den Dereferenzierungs-operator auf den Iterator anwenden, um auf die Memberfunktionen der Objekte zuzugreifen?:
typedef liste<Objects*> ObjectsPtrList; ObjectsPtrList nyobjects; ObjectsPtrList::const_iterator pos; pos = myobjects.begin(); for( ; pos != myobjects.end();++pos) { (*pos)->objectfunction(); }
Laut https://www.cplusplus.com/reference/iterator/ ist ein Iterator doch in den meisten Fällen bereits ein Pointer.
-
Und hinter dem Iterator liegt ein Pointer darum die "doppelte" Dereferenzierung, einmal für den Iterator und einmal für den Pointer.
-
Was würdest du denn sonst erwarten und warum? Das Verhalten 100% konsistent damit, wie sich Iteratoren und Zeiger sonst auch verhalten. Wenn du etwas anderes erwartest, ist davon auszugehen, dass du irgendwelche falschen Vorstellungen von Zeigern oder Iteratoren hast, die wir korrigieren sollten.
-
@C-Sepp sagte in Iteratur Liste:
Laut https://www.cplusplus.com/reference/iterator/ ist ein Iterator doch in den meisten Fällen bereits ein Pointer.
Schau hier nach den möglichen Iteratorklassen: https://en.cppreference.com/w/cpp/iterator
Es geht doch gerade darum, dass du mit dem Iterator unabhängig von der dahinterstehenden Implementierung bist - wichtig ist, dass du mit dem
*
-Operator auf den Wert zugreifen kannst. Und der Wert ist in deinem Beispiel eben ein Pointer. Und den musst du eben nochmal dereferenzieren.Ein * um vom Iterator auf den im Inter
-
Jetzt hab ich's ...Danke!
-
Hey Leute,
folgendes Szenario: Ich habe 3 public vererbte Klassen mit der Basisklasse Base und den davon abgeleiteten Klassen Derived1 und Derived. Base besitzt eine virtuelle Funktion toString(), welche in Derived1 redefniert wird.
Nun möchte ich einmal eine Liste bestehend aus Zeigern vom Typ der Basisklasse, und einmal bestehend aus Objekten
vom Typ der Basisklasse anlegen:
Fall1:typedef list<Base> ShapePtrList1; ShapePtrList myShapes1; myShapes1.push_back(Derived1()); myShapes1.push_back(Derived2()); ShapePtrList1::iterator pos1; pos1 = myShapes1.begin(); for (; pos1 != myShapes1.end(); pos1++) { cout << pos1->toString() << endl; }
Fall2:
typedef list<Base*> ShapePtrList2; ShapePtrList myShapes2; myShapes2.push_back(new Derived1()); myShapes2.push_back(new Derived2()); ShapePtrList2::iterator pos2; pos2 = myShapes2.begin(); for (; pos2 != myShapes2.end(); pos2++) { cout << (*pos2)->toString() << endl; }
Nun wird im Fall2 die in Derived1 redefinierte Version von toString() aufgerufen, wohingegen im Fall die Version aus
Base aufgerufen wird. Worin besteht der genaue Grund für dieses Verhalten? Danke!
-
Was soll denn sonst passieren?
In deinem Fall 1 geschieht das, was man Slicing nennt. Ein Objekt vom Typ Base kann halt nicht auf die Member von Derived zugreifen.
-
Auch wenn das wahrscheinlich nur Rumtesterei ist, der obligatorische Hinweis, dass dein Fall 2 Mist ist, da du die list-items nicht löscht.
Und deine for-Schleifen sind auch nicht so dolle. Warum nutzt du den Initialisierungspart in der for-Schleife nicht!? Und dann gleich mit auto und dann kannst du auch foreach nehmen.
-
@Schlangenmensch : Stimmt, bei der Zuweisung von einem Objekt der abgeleiteten Klasse an ein Objekt der Basisklasse
gehen ja auch die "speziellen" Eigenschaften der abgeleiteten Klasse verloren. Also empfiehlt es sich so eine Liste
über Zeiger zu verwalten?
@Jockelx Okay!
-
@C-Sepp sagte in Iteratur Liste:
Also empfiehlt es sich so eine Liste
über Zeiger zu verwalten?Ja, genauer: über unique_ptr.