wie stellt man einen vector iterator nach außen zur verfügung
-
volkard schrieb:
/*
auskommentiert, weil scheiße
typedef vector<Konto*>::iterator iteratr;
iterator begin(){return KontenVec.begin();}
iterator end(){return KontenVec.end();}
/
vector<Konto> const& getKonten();//jo, das ist gut.Begründung?
-
Bashar schrieb:
volkard schrieb:
/*
auskommentiert, weil scheiße
typedef vector<Konto*>::iterator iteratr;
iterator begin(){return KontenVec.begin();}
iterator end(){return KontenVec.end();}
/
vector<Konto> const& getKonten();//jo, das ist gut.Begründung?
weil die kontenverwaltung keine liste IST, sondern eine liste HAT.
anbool geld_Ueberweisen(unsigned long kontonummer_von, unsigned long kontonummer_nach, float betrag, Spesen *sp);
sieht man, daß kontenverwaltung mehr macht, als nur ne liste zu sein. udn eine klasse sollte auch nur einen zweck haben. dazu gehört auch, daß sie nicht so tut, als sei sie eine andere.
und mit der täglichen welt paßt es auch besser zusammen, da der mitarbeiter des kontenverwalters den kontenverwalter fragt "gibste mir mal ne liste aller konten?" und nicht "sag mir mal das erste konto. sag mir mal das nächste. war das das letzte? sag mit mal das nächste...".
der erste entwurf fühlte sich aber auch schon schlecht an, bevor ich den zweiten sah.
-
surf. schrieb:
was soll die methode getKonten zurückgeben, wie viele konten es gibt?
nee. ne referenz auf die liste aller konten.
wie kann ich dann ein konto in einer methode von spesenverwaltung zugreifen, mit interator, aber wie?
vector<Konto*> const& k=bla.getKonten(); for(vector<Konto*>::iterator i=k.begin();i!=k.end();++i) cout<<i->getName()<<endl;
die anzahl kriegste auch leicht mit
cout<<bla.getKonten().size()<<endl;
kriegst gleich alles auf einmal, was du lesend mit nem vector<Konto*>, also ner kontenliste machen kannst.
-
mein zugriff sieht so aus:
bool Spesen::spesen_Abbuchen(float gesamt_spesen, Kontoverwaltung *ko) { for(Kontoverwaltung::iterator i(ko->begin()); i != ko->end(); ++i) { cout<<i->getName()<<endl; } return true; } [cpp] meine klassen:
#ifndef KONTOVERWALTUNGH_
#define KONTOVERWALTUNGH_class Kontoverwaltung
{
private:
typedef vector<Konto*> KontenVec;
KontenVec konten;
public:
typedef KontenVec::const_iterator iterator;
iterator begin(){return konten.begin();}
iterator end(){return konten.end();}
void konto_Hinzufuegen(unsigned long kontonummer, Konto *konto); // Instanz der Klasse Spesen
bool geld_Ueberweisen(unsigned long kontonummer_von, unsigned long kontonummer_nach, float betrag, Spesen *sp);
};#endif
#ifndef SPESENH_
#define SPESENH_class Spesen
{
private:
float gesamt_spesen;
unsigned int quartal;
public:
Spesen(); // Konstruktor
unsigned int get_Quartal() const;
void set_Spesen(float spesenbetrag);
bool spesen_Abbuchen(float gesamt_spesen, Kontoverwaltung *ko);
};#endif
[/cpp]die klassen sind in verschiedenen header dateien...
compiler meldung:
error C2061: Syntaxfehler : Bezeichner 'Kontoverwaltung'
error C2511: 'spesen_Abbuchen' : Überladene Member-Funktion 'bool (float,class Kontoverwaltung *)' nicht in 'Spesen' gefunden
error C2061: Syntaxfehler : Bezeichner 'Kontoverwaltung'hmm???? cu
-
wozu helfe ich hier überhaupt?
-
hi...ne referenz auf die liste aller konten is da net gut....ich nehme lieber nen pointer, weil ich da in der liste dann was verändern will! und mit referenz hab ich ja nur eine kopie vom orginal...
ja irgendwas stimmt da no no...hmm?cu
-
surf. schrieb:
hi...ne referenz auf die liste aller konten is da net gut....ich nehme lieber nen pointer, weil ich da in der liste dann was verändern will! und mit referenz hab ich ja nur eine kopie vom orginal...
ja irgendwas stimmt da no no...hmm?cu
du scheinst nicht genau zu wissen, was eine referenz ist. eine referenz ist weder ein pointer noch eine kopie, sondern ein anderer name fuer ein bestehendes objekt. d.h du kannst referenzen eigentlich wie zeiger verwenden; mit dem unterschied, dass referenzen immer gueltig sind.
was auch immer
-
was auch immer schrieb:
surf. schrieb:
hi...ne referenz auf die liste aller konten is da net gut....ich nehme lieber nen pointer, weil ich da in der liste dann was verändern will! und mit referenz hab ich ja nur eine kopie vom orginal...
du scheinst nicht genau zu wissen, was eine referenz ist. eine referenz ist weder ein pointer noch eine kopie, sondern ein anderer name fuer ein bestehendes objekt. d.h du kannst referenzen eigentlich wie zeiger verwenden; mit dem unterschied, dass referenzen immer gueltig sind.
ich propagiere aber auch, daß man referenzen nehmen soll, wenn es wie "by-value" aussieht, daß man zeiger sonst nehmen soll.
daß es völliger unfug ist, an das referenz-sein das nichtnullsein als versprechen zu hängen.
insofern halte ich surf. für viel informierter als dich.ich würde als kontenverwalter aber trotdem nur ne read-only-liste rausgeben und verlangen, daß der mitarbeiter neue konten bei mir beantragt über "void konto_Hinzufuegen(unsigned long kontonummer, Konto *konto);". denn immerhin will ich mir offen lassen, daß ich da noch sachen dabei erledige. und überhaupt, mir wird der chef den kopf abreißen, wenn kundenkonten plötzlich ohne ersichtlichen grund verschwunden sind und so.
-
ich würde als kontenverwalter aber trotdem nur ne read-only-liste rausgeben und verlangen, daß der mitarbeiter neue konten bei mir beantragt über "void konto_Hinzufuegen(unsigned long kontonummer, Konto *konto);". denn immerhin will ich mir offen lassen, daß ich da noch sachen dabei erledige. und überhaupt, mir wird der chef den kopf abreißen, wenn kundenkonten plötzlich ohne ersichtlichen grund verschwunden sind und so.
ja ich will ja in der klasse spesen kein konto hinzufügen, die klasse spesen soll nur die spesen welche beim überweisen nach einem bestimmten quartal vom konto abbbuchen...
was könnte da der fehler sein, siehe post oben:
error C2061: Syntaxfehler : Bezeichner 'Kontoverwaltung' error C2511: 'spesen_Abbuchen' : Überladene Member-Funktion 'bool (float,class Kontoverwaltung *)' nicht in 'Spesen' gefunden error C2061: Syntaxfehler : Bezeichner 'Kontoverwaltung'
cu
-
error C2061: Syntaxfehler : Bezeichner 'Kontoverwaltung'
sieht aus, als könnte die datei Spesenkram.h vorher noch die Kontoverwaltung.h inkludieren müssen.error C2511: 'spesen_Abbuchen' : Überladene Member-Funktion 'bool (float,class Kontoverwaltung *)' nicht in 'Spesen' gefunden
folgefehler. vorhin hat das deklarieren ja nicht geklappt.error C2061: Syntaxfehler : Bezeichner 'Kontoverwaltung'
immernoch keine Kontoverwaltung.h inkludiert.
-
hi, ich muss da in der header was ändern:
#ifndef SPESENH_ #define SPESENH_ class Kontoverwaltung; class Spesen { private: float gesamt_spesen; unsigned int quartal; public: Spesen(); // Konstruktor unsigned int get_Quartal() const; void set_Spesen(float spesenbetrag); bool spesen_Abbuchen(float gesamt_spesen, Kontoverwaltung *ko); }; #endif
so funzt es...;-)
einfach nach #define SPESENH_
class Kontoverwaltung;das wusste ich gar nicht!!! irgendwie komischer style...
cu surf.
-
@volkard
das Problem ist aber, dass du dich so a) eher auf einen vector festlegst als mit der Iterator Möglichkeit, was schlecht ist, wenn du zB. merkst, dass eine std::list doch besser geeignet ist und b) du wenn du eine veränderbare Version (also nicht const) anbietest, verletzt du das open-closed Prinzip. Man würde ja auch nichtclass foo { int bar; public: int &set_bar() { return bar; } };
machen.
Aber begin/end Funktionen einzubauen ist auch nicht die wahre Sache.
Hmm, kann mich so gar nicht entscheiden, was schlechter ist
-
kingruedi schrieb:
das Problem ist aber, dass du dich so a) eher auf einen vector festlegst als mit der Iterator Möglichkeit, was schlecht ist, wenn du zB. merkst, dass eine std::list doch besser geeignet ist und b) du wenn du eine veränderbare Version (also nicht const) anbietest, verletzt du das open-closed Prinzip. Man würde ja auch nicht
class foo { int bar; public: int &set_bar() { return bar; } };
machen.
Aber begin/end Funktionen einzubauen ist auch nicht die wahre Sache.nicht-const soll so nicht angeboten werden. hab ich oben schon gesagt.
und was stürt daran, daß es vector ist? die kaputte c++-sprache? ja, nur die. nur ein einziges feature!
statt
vector<Konto*> bla=foo.getKonten(); for(vector<Konto*>::iteraror i=bla.begin();i!=bla.end();++i)
schreibe man
var bla=foo.getKonten(); for(var i=bla.begin();i!=bla.end();++i)
desdawegen schreibe ich ja meinen eigenen präprozessor, weil ich die schnauze von dieser bremsenden standardisierung voll habe.
bis dahin kann man leben mit#define VAR(name,init) typeof(init) name(init) VAR(bla,foo.getKonten()); for(VAR(i,bla.begin());i!=bla.end();++i)
[/cpp]
ups, typeof ist nicht standard. wir gut, daß ich mir da nichts mehr draus mache. nonstandard-code ist einfach lesbarer. hehe.Hmm, kann mich so gar nicht entscheiden, was schlechter ist
ist für mich aber sonnenklar.
-
Ich find Volkards Version eindeutig die bessere, die Klasse Kontoverwaltung ist kein
Container und somit hat darin weder ein begin noch ein end was verloren.
Und der Zugriff über einen Vector mit Kontozeigern ist ne schöne Lösung, vor allem
da man beim Aufruf von getKonten ja bereits weiß wieviele es gibt und der Vector
deshalb ja nicht verändert werden muss während dem bearbeiten, denn es ist Sache
von Kontoverwaltung Konten zu löschen und neue hinzuzufügen, nicht von einer
aussenstehenden Klasse.
-
@volkard
bastelst du dir dein eigenes "auto", so wie es für C++0x vorgeschlagen ist? Hört sich gut an. Wie weit bist du schon?
-
kingruedi schrieb:
@volkard
bastelst du dir dein eigenes "auto", so wie es für C++0x vorgeschlagen ist? Hört sich gut an. Wie weit bist du schon?es hat damit angefangen, daß ich zum mingw-studio umgestiegen bin und mal foreach benutzt habe. nach ein paar kläglichen versuchen blieb dann dies hier:
#define FOREACH(i,container)\ for(typeof((container).getBegin()) i=(container).getBegin();i!=(container).getEnd();++i)
und gleich auch noch
#ifndef RANGE_H #define RANGE_H #include <cstddef> template<class T> struct Range{ private: T begin; T end; public: Range(){ } Range(T _begin,T _end): begin(_begin), end(_end){ } T getBegin(){ return begin; } T getEnd(){ return end; } size_t getSize(){ return end-begin; } }; template<class T> bool operator==(Range<T> a,Range<T> b){ return a.getBegin()==b.getBegin() && a.getEnd()==b.getEnd(); } template<class T> bool operator!=(Range<T> a,Range<T> b){ return !(a==b); } template<class T> inline Range<T> makeRange(T begin,T end){ return Range<T>(begin,end); } #endif
naja, und wie's so kommt, schreib ich keine normale schleife mehr.
int main(){ FOREACH(i,makeRange(0,1000000)) // if(isPrime(i)) { cout<<i<<' '; // Sleep(100); // Beep(1000,50); } return 0; }
(die testfunktion, womit ich mein um faktor 10 schnelleres cout perfektioniert habe (nicht, weil ich speed brächte, sondern weil ich einfachheit brauche.).)
das makro VAR hab ich in zwei oder drei funktionen mal benutzt, und es fühlt sich so geil an, daß ich denke, ich werde es nur noch benutzen, sobald man "var i=5" schreiben kann.
entsprechend haben meine container nicht mehr ne klasse iterator drin und const_iterator und so nen quark.
siehst ja, daß ich einfach auf typeof(getBegin()) aufsetze.
ich ersetze auch ifstream und ofstream. und der herr gebe, daß mir mal einer sockets reinbaut.
ich sage übrigens getBegin(), weil es aussage "sagt mit den anfang", während begin() sagen kann "sag mir den anfang" oder "fange an" oder "setze den anfang", was mir einfach zu uneindeutig und denkaufwändig ist.ich werde brigens demnächst gar keine system-header außer gelegentlich der <windows.h> mehr einbinden. den wichtigen typ size_t ziehe ich mit mit typedef typeof(sizeof(0)) size_t und sichere ihn gelegentlich mit STATIC_ASSERT ab. rest ist irrelevant.
den präproz, der "var bla=...;" zu "typeof(...) bla(...);" machen kann, halte ich für kein problem. ich habe, denke ich, gelöst, wie ich ihn der gcc unterjuble.
evtl hab ich endlich nen ansatz für verständlich hinschreibbare echte compilezeitprogramme. muß daran noch basteln. aber zuerstmal baue ich an c++ weiter mit nur trivialsten änderungen wie var.
muß leider gerade steuererklärung fertigmachen und zeugnisse vorbereiten, weshalb ich in der forschung nicht weiterkomme.
-
ich sage übrigens getBegin(), weil es aussage "sagt mit den anfang", während begin() sagen kann "sag mir den anfang" oder "fange an" oder "setze den anfang", was mir einfach zu uneindeutig und denkaufwändig ist.
Da muss ich widersprechen. Du schreist nicht begin() sondern vec.begin(), da vec ein Container ist, fallen "fange an" oder "setze den anfang" weg da sie in diesem Kontext Schwachsinn sind.
Und auch wenn ich jetzt wahrscheinlich gekreuzigt werde aber ich finde, dass oft benutzte Befehe auch nicht eindeutige Namen haben dürfen. Sonst hat man nur umso mehr Tiparbeit und schrecklich unlesbar lange Zeilen.
Aber damit, dass typeof im Standard fehlt hast du vollkommen recht, hoffen wir mal, dass C++0x da helfen wird.
-
Irgendwer schrieb:
Da muss ich widersprechen. Du schreist nicht begin() sondern vec.begin(), da vec ein Container ist, fallen "fange an" oder "setze den anfang" weg da sie in diesem Kontext Schwachsinn sind.
ist in deinem kontext einleuchtend. aber bei mir nicht, da getBegin() und getEnd() nicht häufig benutzte methoden sind.
fast alle verwendungen fallen schonmal durch FOREACH weg. und die übrigen fliegen zum größten teil, weil ich auch gleich die algos der stl reimplemetiere, daß sie statt iteratorpaaren gleich objekte des typs iteratorpaar (bei mir noch namens Range) nimmt. fast immer will ich nämlich den ganzen vector ausgeben/sortieren/durchsuchen..., da hat mich das getippe von begin() und end() schon immer genervt.Und auch wenn ich jetzt wahrscheinlich gekreuzigt werde aber ich finde, dass oft benutzte Befehe auch nicht eindeutige Namen haben dürfen. Sonst hat man nur umso mehr Tiparbeit und schrecklich unlesbar lange Zeilen.
ich suche halt den komplizierteren ausweg.
edit: habe bezüglich Range auch noch ein dickes problemchen: bei char str[]="hello"; FOREACH(i,makeRange(str,str+5)) will ich immer *(str+x) sehen, bei FOREACH(i,makeRange(0,100)) winn ich immer auf (str+x) ohen * zugreifen. da stimmt was nicht. sollte erstere sorte eher Sequence heißen? oder gibst doch nen weg, die beiden sorten Range als eigentlich gleich aufzufassen?
-
aber das was ich zuletzt habe, passt ja oder wie?
cu surf.