Art des Iterators implementierungsspezifisch -> Was tun?



  • Hallo zusammen. Ich habe folgende Problemstellung:

    Für eine Klasse "Graph" macht es Sinn, einen Mechanismus anzubieten, um über alle Knoten oder alle Kanten des Graphen zu iterieren.

    Andererseits soll meine Graph-Klasse eine allgemeine Schnittstelle sein. In was für einer Art Container die Knoten und Kanten vorliegen (vector, list, set, map...) ist also ein Implementierungsdetail und wird erst von Unterklassen näher spezifiziert.

    Eine Methode wie getNodesBegin() fällt demnach flach, da sie ja als Typ den Iteratortyp haben müsste, also je nach Implementierung list::iterator, map::iterator oder so.

    In Java gäbe es dazu die Oberklasse Iterator, so wie es ja die Oberklasse Collection gibt. Wie gehe ich soetwas nun in C++ an?

    Kurz und bündig lautet mein Problem also: Gegeben eine Klasse, welche einen Container (noch) unbekannter Art kapselt. Finde einen Weg, dennoch allgemein über dessen Elemente zu iterieren...

    Ich dachte zunächst an eine eigene Klasse "NodesIterator", die entsprechend ->, *, ++ und == überlädt, aber nur als abstrakte Methoden (also virtuell).

    Eine Unterklasse von Graph, die dann Knoten in einem vector speichert, würde dann auch eine überladene Version von NodesIterator anbieten, welche eben den vector-iterator benutzt. Man hat sozusagen eine Wrapper-Klasse geschaffen.

    Ist dies eine gute Lösung? Man hat ja dann recht viele virtuelle Funktionsaufrufe...

    Gruß,
    Supertramp



  • Irgendwo gibst du auf jeden Fall den Container an (als Template-Parameter o.ä.) - und dann kannst du auch per 'typename CT::iterator' den dazu passenden Iteratortyp herausfinden.



  • Wenn der Typ des Iterators noch unbekannt ist, und du trotzdem die Standard-Iteratoren bzw. deren Konzept beibehalten willst, solltest du in der getNodesBegin() einen Template-Typ zurück geben. Dann kann die ableitende Klasse den Typ per Template-Parameter selber setzen.

    Wenn du keine Templates benutzen willst, solltest du einen Adapter-Iterator definieren, den die ableitenden Klassen implementieren müssen.



  • Supertramp schrieb:

    Andererseits soll meine Graph-Klasse eine allgemeine Schnittstelle sein. In was für einer Art Container die Knoten und Kanten vorliegen (vector, list, set, map...) ist also ein Implementierungsdetail und wird erst von Unterklassen näher spezifiziert.

    Soll/kann deine Graph-Klasse ein Template sein?

    edit: oops, altes Tab 😞



  • Danke für soviel konstruktive Beiträge.

    Also, den Typ des Containers wollte ich eigentlich nicht als Template-Parameter angeben sondern von diversen Unterklassen spezifizieren lassen. Unter Umständen wird ja nicht mal ein echter Container benutzt und man muss sich für die Iteratorklasse ganz was neues einfallen lassen.

    Mit dem Template-Typ, würde das so aussehen?

    template<class Iter> Iter getNodesBegin();
    

    Ich habe bisher fast nur Java gemacht, daher sind mir so subtile Sachen nicht ganz geläufig...

    Die Adapter-Lösung, ist das nicht das, was ich eingangs beschrieben habe? Oder wieder ganz etwas anderes?

    Schönen Gruß nochmal,
    Supertramp



  • Das mit dem Template hast du schon richtig gemacht. Es hat halt den Vorteil, das letztendlich der Benutzer der Klasse selbst bestimmt, was er da einsetzt. D.h. der Benutzer bestimmt selbst, was er da für einen Typ einsetzt.

    Bei einem Adapter oder Interface ist der Nachteil (sehe ich jedenfalls so), das du eine Iterator-Fähigkeit vorgeben mußt (z.b. nur in einzelnen Schritten nach vorne iterieren). Evtl. sind die Fähigkeiten so eingeschränkt, das du dann letztendlich wieder einen Container oder Iterator-Typ vorgeben kannst. Bei Templates ist das nicht so.

    Naja, man kann halt nicht alles auf einmal haben, sonst würde es auch nur eine technische Lösung geben.

    Es gibt noch folgendes: http://www.boost.org/libs/iterator/doc/index.html
    Wird aber für einen C++-Umsteiger vielleicht dann auch zu viel des Guten sein. 😉



  • Ausgezeichnet 🙂

    Danke nochmals für die hilfreichen Antworten.

    Die Boost-Library führ ich mir dann bei Zeiten mal zu Gemüte, so dringend ist das ja nu nicht 😃


Anmelden zum Antworten