Objekt, dem mehrere andere Objekte zugeordnet sind?!



  • maSu schrieb:

    Einerseits hast du recht chrische, andererseits schadet es nicht alternativen zu kennen, falls man mal nicht zugriff auf alles mögliche hat, es also irgendwie "zu fuß" schaffen muss.

    Dann schreib dir halt zur Übung dein eigenes dynmisches Array, aka std::vector, und du kannst ja auch gerne dieses dann benutzen.
    Aber du wirst in C++ immer darauf Zugriff haben, abgesehen davon erfüllt der std::vector einige Eigenschaften, so dass du ihn auch in Verbindung mit C-APIs nutzen kannst.



  • Hallo

    Wann hast du denn keinen Zugriff auf std::vector? Klar kann man auch alles selber machen, aber dann wirst du nicht fertig. Warum implementierst du nicht cin und cout selber?

    chrische



  • jaja is ja gut *in die ecke geht und sich 5 minuten schämt* 🙂

    und danke @all 🙂



  • maSu schrieb:

    class zimmer{
    private: //vll noch nen Zimmername? ne Quadratmeteranz. oder so was... kA
    	float preisZimmer;
    public:
    	void getInneneinrichtung(); //Get... aber kein Rückgabetyp? OO
    };
    
    class haus{
    private:
    	float preisHaus;
    
    public:
    	void getPreis(); //float GetPreis () const;
    	zimmer meinZimmer; //std::vector / std::map (std::string name, zimmer)
    };
    

    Hmm?
    sieht alles sehr komisch aus, find ich...
    die einrückung ist auch nicht sooo prall...

    class haus {
      public:
        ...
    };
    

    wenn schon...

    bb



  • ohne vector
    // ausn kopf, muss nicht so funzen

    #include <vector>
    class Zimmer
    {
    private:
        double _Preis;
    public:
        double GetPreis();
        Inneneinrichtung GetInneneinrichtung();
    };
    
    class Haus
    {
    private:
        double _Preis;
    
    public:
        Haus(int zimmerAnzahl)
        {
            _meineZimmer = new zimmerAnzahl[zimmerAnzahl];
        }
        ~Haus()
        {
            delete[] _meineZimmer;
        }
        void GetPreis();
        Zimmer* _meineZimmer;
    };
    
    .
    Using:
    .
    
    Haus haus = Haus(10); // 10 zimmer
    double hausPreis = haus.GetPreis();
    double zimmerPreis = haus._meineZimmer[4].GetPreis();
    

    und schon sieht man stinkenden code (an dem "_") - die zimmer sollten nicht frei zugaenglich sein, sei es ein vector oder ein roher zeiger - stichwort kapselung
    die zimmer sollten immer ueber eine schnittstelle von Haus laufen - einmal erstellt sollten die zimmer nicht mehr oder weniger werden koennen (es sei denn man implementiert eine "Ausbauen" methode) - so wie es oben ist koennte man die zimmeranzahl von aussen manipulieren

    besser ist "GetZimmer(x).Preis" usw welches dann auch prueft ob es x zimmer gibt

    // grr - ich sollte meine beitraeger genauer lesen vorm abschicken #gg



  • ahh ja, wunderbar 🙂

    so in der Art dachte ich mir das, war aber noch zu unsicher mit Klassen um das so hinzukriegen - hatte das im Code statt im konstruktor woanders geschrieben (ich sag jetzt nicht wo, ist mir echt zu peinlich ^^) und deswegen klappte das nicht und ich hab dann schließlich hier gefragt 😉

    also nochmal danke an alle, besonders an Mr Evil und Simon2 🙂



  • Hallo

    Auch wenn du mich ausgeschlossen hast 😉 , solltest du unbedingt std::vector benutzen. Warum wurde ja bereits mehrfach gesagt und geschrieben.

    chrische



  • joa vector ist schon gut, nur wollt ich auch eine Ahnung haben, wie es ohne gehen könnte 😉

    In meinem Proggi (mini-möchtegern-datenbank 😉 ) ist es auch mit vector nun gemacht. das Handling ist doch recht einfach und für mich auch sicherer und effizienter wohl auch, sogar wenn ich es nutze 😉



  • maSu schrieb:

    joa vector ist schon gut, nur wollt ich auch eine Ahnung haben, wie es ohne gehen könnte ;)...

    Hast Du auch schonmal gesagt:
    "Ich wollte mal wissen, wie man das ohne (char-)Arrays macht!" ?

    Seltsamerweise hört man zwar immer wieder mal die Begründung (meistens von "Frischlingen" 😉 )
    "Ich wollte mal wissen, wie man das ohne <xyz> macht!" (<xyz> ist dabei aus {"vector", "string", "map", ... })
    aber denselben Anspruch mal an Arrays anzulegen, kommt Anfängern anscheinend nie in den Sinn.

    Dahinter scheint immer doch noch die alte (Irr-)Meinung zu stehen, Arrays seien irgendwie "echter" als die StdLib-Komponenten... mal sehen, ob diese Nummer irgendwann mal ausstirbt, oder ob in alle Ewigkeit (immer neue) C++-Anfänger damit infiziert werden.

    Gruß,

    Simon2.



  • Hmm, ich mahc mir grade Gedanken wie man eine Zugriff á la

    einhaus.zimmer[5]
    

    ermöglichen kann ohne dem Klienten gleich den ganzen Container über public Zugriff in die Hand zu geben. Ein erster Ansatz:

    //traits für die Rückgabetypen des op[] bei verschiedenen Container-Typen
    template <class T> //allgemein, STL-kompatibel (vector, deque...)
    struct ref_types_of {
      typedef typename T::reference reference;
      typedef typename T::const_reference const_reference;
    };
    
    template <typename key, typename val, class comp, class alloc> //partiell spezialisiert für map, gleiches muss für multimap gemacht werden...
    struct ref_types_of< std::map<key,val,comp,alloc> > {
      typedef val& reference;
      typedef val const& const_reference; //auch wenns kein op[] const gibt fuer map
    };
    
    template <typename T> //partiell spezialisiert für Arrays/Pointer
    struct ref_types_of<T*> {
      typedef T& reference;
      typedef T const& const_reference;
    };
    
    //Klasse für Zugriffseinschränkung auf Container mit op[]
    template <class Cont>
    class accessforward {
      Cont& container;
    public:
      accessforward(Cont& cont) : container(cont) {}
    
      template <typename Key> //soll für alle möglichen Typen gehen, die Konvertierung findet dann ggf. beim Aufruf von container[key] statt
      typename ref_types_of<Cont>::reference operator[](Key const& key) {
        return container[key];
      }
    
      template <typename Key>
      typename ref_types_of<Cont>::const_reference operator[](Key const& key) const {
        return container[key];
      }
    };
    
    class Zimmer;
    class Haus {
      std::vector<Zimmer> die_zimmer;
    public:
    
      accessforward<std::vector<Zimmer> > zimmer;
    
      Haus(size_t nzimmer) : die_zimmer(nzimmer), zimmer(die_zimmer);
    };
    
    //[using]
    Haus meinhaus(5);
    meinhaus.zimmer[4].getInneneinrichtung(); //accessforward::operator[] leitet weiter an std::vector<Zimmer>::operator[]
    

    Man könnte natürlich direkt den Container in accessforward einbauen, allerdings hätte dann Haus genauso eingeschränkten Zugriff auf den Container wie alle anderen auch.



  • warum nicht mit getter ?

    Zimmer zimmer = einHaus.GetZimmer(5);

    in GetZimmer kann dann auch die pruefung von statten gehen



  • Mr Evil schrieb:

    warum nicht mit getter ?

    Zimmer zimmer = einHaus.GetZimmer(5);

    in GetZimmer kann dann auch die pruefung von statten gehen

    Das ist ja etwas ganz anderes als er basteln wollte.
    Da man aber so oder so angeben muss auf was man von außen Zugriff haben darf, kann man die Methoden meist auch direkt in die Klasse einbauen. Pumuckls Vorschlag würde einem aber Arbeit sparen, wenn man diese Art von Forward mehrfach benötigt.

    Allerdings hat diese Methode ein paar Nachteile:
    -Man kann zimmer austauschen gegen ein anderes accessforward Objekt
    -Der Benutzer kann Referenzen darauf speichern und nach einem Austausch wären diese ungültig
    -Man muss das zimmer Attribut immer dabehalten - macht also zukünftige Umstrukturierungen eventuell problematisch



  • was wäre wenn zimmer einfach eine const reference auf den vector ist?



  • Shade Of Mine schrieb:

    was wäre wenn zimmer einfach eine const reference auf den vector ist?

    Dann kann nur op[] const für den vector aufgerufen werden, der dann wiederum nur const referenzen auf die Zimmer liefert -> Zimmer sind auch für ein non-const Haus nicht veränderbar.


Anmelden zum Antworten