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 nichtstd::vector <Field*>::iterator iterschreiben müssen.
Joe
-
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 iterschreiben 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.