Iteratoren und Information-Hiding



  • Hallo!

    Ich habe ein Verständnisproblem bei der Verwendung von Iteratoren.
    In meinem Fall habe ich mit einer Darstellung einer Datenbank zu tun. Also gibt es eine Klasse "Table", die wiederum eine Klasse "Fields", die wiederum eine Ansammlung von Instanzen der Klasse "Field" enthält.

    class Table
    {
      private:
      Fields *fields_;
    
      public:
      Fields* getFields();
    }
    
    class Fields
    {
      private:
      std::vector <Field*> fields_;
    }
    
    class Field
    {
      private:
      std::string name_;
      std::string datatype_;
      ...
    }
    

    Jetzt möchte ich "von außen" über die Elemente in Fields::fields_ iterieren können, d.h. einen Iterator definieren, wo ich einfach mit ++ zum nächsten Element kommen.

    Etwas der Art

    Iterator iter;
    //hier möchte ich mich nicht um die interne Struktur von "Fields" kümmern
    for (iter=table->getFields()->begin();iter != table->getFields()->end();iter++)
    {
      ...
    }
    

    hätte ich gerne
    Mein Problem ist dabei, daß ich die Datenstruktur dahinter (diesen std::vector) verstecken möchte, da es sich ja um eine interne Repräsentation handelt.

    Könnt ihr mir dabei weiterhelfen?

    Danke und Gruß,
    Joe



  • du weißt, dass

    std::vector <Field*> fields_
    

    private ist und damit kein zugriff "von außen" möglich ist....



  • Bei deinem Design kannst du das private direkt weglassen - getFields() hat die selbe Wirkung, als ob du direkt auf die privaten Daten zugreifen würdest.

    Zum Kernproblem: Dazu mußt du die entsprechenden Iterator-Definitionen in deiner Field-Klasse bereitstellen:

    class Fields
    {
    public:
      typedef vector<Field*> F_Vec;
      typedef F_Vec::iterator iterator;
      iterator begin() {return _data.begin();}
      iterator end() {return _data.end();}
    private:
      F_Vec _data;
    }
    


  • ... da war jemand schneller (bezieht sich auf das vorherige)

    weiß ich! 🙂
    Das Ganze soll nur der Veranschaulichung dienen, weil sonst niemand das Problem versteht.

    Genau dort ist auch das Problem. Wenn ich das Zeug public mache, dann weiß ich ja von außen, daß es sich um einen std::vector handelt.
    Ich will eben außen nicht

    std::vector <Field*>::iterator iter
    

    schreiben müssen.

    Joe



  • @CStoll:

    typedef vector<Field*> F_Vec;
      typedef F_Vec::iterator iterator;
    

    Damit ist doch wieder außen sichtbar, welche Datenstruktur ich innen verwendet habe, oder?

    Ich werde auf jeden Fall einmal damit "herumexperimentieren". Danke

    Joe



  • Du kannst auch einen eigenen Fields-Iterator schreiben 😉

    class Fields
    {
    public:
      class iterator
      {
        iterator(const Fields* fld,vector<Fields>::iterator pos)
          : _fld(fld),_pos(pos) {};
        friend class Fields;
      public:
        iterator& operator++() {++_pos;return *this;}
        iterator  operator++(int);
        //...
        //alle benötigten Iterator-Operationen
      private:
        const Field* _fld;
        vector<Fields*>::iterator _pos;
      };
      friend class iterator;
    
      iterator begin() {return iterator(this,_data.begin());}
      //...
    private:
      vector<Fields*> _data;
    }
    

    joerider schrieb:

    Ich will eben außen nicht

    std::vector <Field*>::iterator iter
    

    schreiben müssen.

    Joe

    Deswegen ja die typedef's - dann schreibst du von außen nur noch:

    Fields::iterator iter;
    

    (und dem Nutzer kann es letztendlich egal sein, ob hinter Fields::iterator nun ein normaler vector-Iterator, set-Iterator oder eine eigene Klasse steht - solange diese die benötigten Operatoren (++,--,*,->,...) bereitstellt.



  • Überdenke dein Design.


Anmelden zum Antworten