Programmieren mit C++

Borland C++

32-Bit-Programmierung

Iterator durch List-Container

Wie realisiert man einen Iterator durch Container-Klassen?

Frage

In einer Anwendung, die Container verwendet, sollte man zunächst eine Klasse deklarieren, die einen Item in einem Container repräsentiert.

class CMyClass : public CObject { 
    // programmspezifische Member
    ... 
}; 
 
typedef CTypedPtrList

Eine separate Klasse enthält das tatsächliche Container-Objekt.

class CMyClassList : public CObject { 
    private: 
        TMyList List; 
        // Ggfs. andere Datenmember 
    public: 
        // übliche Methoden (Konstruktor, Destruktor etc.
        void Flush(void); 
        BOOL Add(CMyClass *ptr); 
        CMyClass *Find(...); 
        BOOL Del(...); 
}; 

Ist der Container mit einem Interface-Objekt wie Tree-Control, List-Control oder anderen verbunden, muß eine Iteration durch den Container möglich sein, damit Aktionen für jedes Element des Containers, abhängig von einer Bedingung, erfolgen können. Hierzu sind verschiedene Ansätze denkbar.

Lösung

Die einfachste Lösung wäre, eine Listen-Variable im öffentlichen Teil der Deklaration zu plazieren, so daß anschließend über dieses Member ein direkter Zugriff auf den Container möglich wäre. Allerdings verstößt dieser Ansatz gegen das fundamentale OOP-Gebot der Kapselung.

Öffentliche List-Variable

Eine andere Vorgehensweise besteht darin, eine öffentlich deklarierte Member-Funktion zu verwenden, die über eine ebenfalls bereitgestellte Callback-Funktion die einzelnen Elemente bearbeitet. Dies ist jedoch etwas verwirrend, da die bereitgestellte Callback-Funktion üblicherweise eine Member-Funktion einer anderen Klasse ist, so daß für jede Callback-Funktion in der Klasse CMyClassList eine überladene Member-Funktion vorhanden sein muß. Ist die Callback-Funktion hingegen eine statische Non-Member-Funktion, so muß ein DWORD-Argument zur Übergabe des „this“-Zeigers mitgeführt werden, der innerhalb der Klasse auf einen Zeiger für das entsprechende Objekt gecastet werden muß, bevor man eine Methode aufrufen kann, die dann tatsächlich die Aktion auf das Container-Element ausführt.

Callback-Funktion

Wesentlich einfacher und eleganter ist hingegen der Einsatz einer speziellen Iterator-Klasse, wodurch sich die Klassen-Deklaration etwas verändert.

class CMyClassListIterator; 
 
class CMyClassList : public CObject { 
    private: 
        TMyClassList List; 
        // Ggfs. weitere Member und Daten
    public: 
        // übliche Methoden (Konstruktor, Destruktor etc.
        void Flush(void); 
        BOOL Add(CMyClass *ptr); 
        CMyClass *Find(...); 
        BOOL Del(...); 
   // Neu: Iterator-Member
     friend CMyClassListIterator;       
}; 

Die neue Iterator-Klasse ist wie folgt definiert:

class CMyClassListIterator : public CObject { 
  private: 
     CMyClassList& Owner; 
     POSITION Pos; 
  public: 
     CMyClassListIterator(TProcess& obj) : CObject(),Owner(obj) 
     { Reset(); } 
     void Reset(void)                
     { Pos = Owner.List.GetHeadPosition(); } 
     void Next(void)                 
     { Owner.List.GetNext(Pos); } 
     CMyClass *Current(void)         
     { return (CMyClass*)Owner.List.GetAt(Pos); } 
     BOOL IsDone(void)               
     { return (Pos == NULL) ? TRUE : FALSE; } 
}; 

Alles, was jetzt noch notwendig ist, um die Liste zu durchlaufen, ist der nachfolgende Codeblock:

Iterator-Klasse

CMyClassList MyList; 
........ 
CMyClassListIterator iterator(MyList); 
while (!iterator.IsDone()) { 
    CMyClass *ptr = iterator.Current(); 
 
    iterator.Next(); 
}; 

Auf ptr kann beliebig zugegriffen werden, jedoch darf ptr nicht gelöscht werden. Der Inhalt, auf den der Zeiger verweist, kann beliebig manipuliert werden. Es ist ebenso möglich, geschachtelte Iteratoren zu implementieren. Ein positiver Seiteneffekt dieser Implementation ist, daß der komplette Code für das Durchlaufen und Bearbeiten der Containerelemente in einer Funktion zusammengefaßt ist und insbesondere keine Callback-Funktionen anfallen. Des weiteren leistet diese Vorgehensweise auch eine Datenkapselung, da das Listenobjekt nicht direkt sichtbar ist.

Code zum Durchlaufen der Liste





Sachgebiet


© 2009-2012 by Alojado Publishing. Alle Rechte vorbehalten. Ausgewiesene Marken gehören ihren jeweiligen Eigentümern.
Mit der Benutzung dieser Seite erkennen Sie die Nutzungsbedingungen und die Datenschutzerklärung an. Der Betreiber übernimmt keine Haftung für den Inhalt verlinkter externer Internetseiten.
Seite erzeugt 2012-05-20 02:23:53 von textarchiv.alojado.de