wie stellt man einen vector iterator nach außen zur verfügung



  • hi, ich habe eine klasse:

    #ifndef __KONTOVERWALTUNGH__
    #define __KONTOVERWALTUNGH__
    
    class Kontoverwaltung
    {
        private:
    		typedef vector<Konto*> KontenVec;
    		KontenVec konten;
    	public:
    		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
    

    ich hab eine 2te klasse spesenverwaltung, ich will auf den vector in klasse kontenverwaltung zugreifen!!! entweder muss ich den vector iteratoren nach außen zur verfügung stellen, oder zumindest sowas wie getSize() und getItem(i), damit von außen einer an die konten kommt... lieg ich da richtig??
    wenn ja wie macht man das???

    cu 👍



  • #ifndef __KONTOVERWALTUNGH__
    #define __KONTOVERWALTUNGH__
    
    class Kontoverwaltung
    {
        private:
    		vector<Konto*> KontenVec;
    		KontenVec konten;
    	public:
    
    /*
    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. 
    
    		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
    


  • vector<Konto*> const& getKonten();//jo, das ist gut.
    

    was soll die methode getKonten zurückgeben, wie viele konten es gibt?
    wie kann ich dann ein konto in einer methode von spesenverwaltung zugreifen, mit interator, aber wie?

    cu



  • 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.
    an

    bool 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 nicht

    class 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.


Anmelden zum Antworten