selbes Objekt in mehreren Klassen nutzen



  • Hallo,
    mein Problem ist folgendes:
    Ich habe 3 Klassen. Die Klasse CSettings, Cdialog und CGeneral.
    für was die einzelnen klassen stehen ist ja jetzt egal.
    nun möchte ich , dass dasselbe objekt der klasse CSettings in klasse Cdialog und CGeneral verfügbar ist.
    wie kann ich das realisieren?

    greetz



  • Das geht wohl am besten mit einem Pointer auf das Objekt^^



  • thx für die schnelle antwort.
    und wo muss ich dann das objekt erzeugen?



  • Naja, auf dem Heap am besten^^

    class foo //Wird überall gebraucht
    {
    ...
    }
    
    class dialog //Hält einen Foo*
    {
    public:
        dialog(foo *att1) { m_foo = att1; }; //Konstruktor der den zeiger der klasse auf das übergebene foo objekt setzt.
    private:
        foo *m_foo; //Der Zeiger auf das Foo-Objekt
    }
    
    class dialog2  //Hält ebenfalls einen Foo*
    {
    public:
        dialog2(foo *att1) { m_foo = att1; };
    private:
        foo *m_foo;
    }
    
    int main()
    {
        foo *temp = new foo;
        dialog quit(temp); //Quit-Dialog mit Zugriff auf temp
        dialog2 save(temp); //Save Dialog mit Zugriff auf temp
        ....
       delete temp; //Aufräumen nicht vergessen
    }
    

    Innerhalb der dialog-klassen kann dann über m_foo-> auf das Temp-Objekt zugegriffen werden.

    Eine andere Möglichkeit wären globale Variablen, die sollten jedoch gemieden werden.



  • --- Doppelpost, bitte löschen ---



  • ok hat sich erledigt -.-
    -bitte löschen ^^



  • Hallo,

    The-Kenny hat hier die typische Vorgehensweise beschrieben.
    Anderer Weg:
    Sofern nur ein Objekt der Klasse CSettings im gesammten Programm gebraucht wird (ist nur eine Vermutung auf Grund des Namens), so empfiehlt es sich hier dieses Objekt als singleton auszulegen.

    Jedes Object das dann CSetting braucht ruft dann irgendwo intern die statische Methode

    CSettings &settings = CSettings.instance();
    

    auf. Dieser Aufruf gibt dann immer das gleiche Objekt zurück, egal wie oft du es aufrufst.

    Suche am besten in der englischen Version von Wikipedia nach design-patterns.

    Gruß



  • aaah linu(x)bie du hast es erfasst -.-
    ma ltesten was denn so funktioniert ^^
    big thx !



  • Singletons sind generell böse, sollte man sich gleich garnicht angewöhnen.
    Erzeug das Objekt in deiner main() Funktion (bzw. InitInstance oder was auch immer), und gib es per Pointer an alle Klassen die es benötigen (z.B. als Parameter des Konstruktor, oder als Parameter bei allen Funktionen die es benötigen).



  • wieso sind singeltons böse?
    die umsetzung war jetzt relativ leicht.
    allerdings funktionierts auch noch nich richtig ^^

    gibts keine einfachere Methode, als jeder funktion das Objekt zu übergeben?
    sind inzwischen n ganzen haufen funktionen.

    greetz



  • sW00p schrieb:

    wieso sind singeltons böse?
    die umsetzung war jetzt relativ leicht.
    allerdings funktionierts auch noch nich richtig ^^

    die umsetzung ist eben nicht ganz so einfach. es gibt viel zu beachten, viel falsch zu machen.

    schau mal hier, da wird auch kurz auf singletons eingegangen:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-155350.html

    gibts keine einfachere Methode, als jeder funktion das Objekt zu übergeben?
    sind inzwischen n ganzen haufen funktionen.

    zeiger zu übergeben ist das gebräuchlichste. Wir wissen nicht, wozu du das brauchst, aber solange es nicht zwingend(!) ist, dass das Objekt einzigartig ist, ist das singleton gefährlich. Eben weil sich mal was ändert, und schwupps hast du mehrere objekte von dem typ.

    Ansonsten kannst du auch objektzeiger innerhalb der Klassen speichern, dann brauchst du den nicht an jede memberfunktion übergeben(übergibs einfach im constructor, vielleicht bietet sich bei dir auch ein factory pattern an, dann wird da halt automatisch der zeiger übergeben. aber für mehr tipps fehlen halt informationen ;)).



  • ich habe halt die klasse CSettings, um darin einstellungen zu speichern, die in dem Programm (Gui) gemacht werden.und dann eben noch andere klassen in dem programm.
    aber von allen klassen müssen auch die einstellungen ausgelesen und gespeichert werden. sprich von überall muss der zugriff auf dasselbe objekt gewährleistet sein.
    greetz



  • also ich abe jetzt mal probiert, das ganze wie pointerübergabe umzuarbeiten, habe nun aber folgendes problem:

    ich rufe mal einen menüpunkt auf bei dem sich ein neues dialogfeld öffnet.
    mit der DoModal() funktion
    da kann nich ja jetzt nicht einfach ein objekt übergeben.
    ist es möglich vielleicht in der haupt klasse ein objekt "CSettings settings;" zu erzeugen und in in allen anderen klassen jeweils ein objekt der haupt-klasse über dass sie dann auf das objekt der CSettings klasse zugreifen können?
    oder würde dabei dann nicht ein und dasselbe objekt benutzt werden?
    ich denke da an sowas wie:

    objektinklasse->CSettingsobjekt->zugriffaufdatenvonCSettings

    /EDIT/

    habs grade mal getestet, also der zugriff funktioniert schonmal.
    jetzt nur zurück zu der frage:
    wird da imemr dasselbe objekt der CSettings klasse verwendet?
    da wär halt schon essentiell wichtig ^^



  • Hallo,

    also sofern Du Probleme hast das "einmal-erzeugte" Objekt an alle weiteren Bedürftigen weiterzugeben, dann hast Du schon mal ein grundlegenden Designfehler.

    Hier noch mal die Vorgehensweise:

    1.) Erzeuge das Objekt auf obersten (gebrauchten) Ebene. Dh. im schlimmsten Fall in der main().
    2.) Da alle anderen Objekte direkt oder indirekt in der obersten Ebene instanziert wurden (das kannst Du Dir als Baumstruktur vorstellen), ist es doch das Intuitivste diesen (Unter-)Objekten eine Referenz auf das gefragte Objekt zu übergeben (zB jeweils im Konstruktor) und dann u.U. weiterzugeben.

    Diese Vorgehensweise ist zwar die intuitivste, macht aber nur dann Sinn wenn die "Baumtiefe" nicht alzu hoch ist, (dh die Anzahl der Weitergaben nicht zu hoch ist).

    Wenn es Dir zu aufwändig ist für alle Klassen die die CSetting nutzen entsprechende Methoden zu schreiben, dann nutze Mehrfachvererbung:

    class NeedSettings 
    {
    public:
    void attachSettings(Settings &settings) {
    this->settings = settings;
    }
    
    private:
    CSetting &settings;
    }
    
    class A : NeedSettings {
    //
    }
    
    class B : NeedSettings {
    //
    }
    

    Bzw Du verzichtest auf ein Settings-Objekt und sagst: "Jedes Objekt das Zugriff auf Settings hat, ist auch ein CSettings objekt". Dazu musst Du CSettings entsprechend anpassen.

    Ist es tatsächlich notwendig, dass alle Klassen direkten Zugriff auf dieses Objekt brauchen?
    Falls ja, dann ist meines Erachtens das Singleton doch die einfachste Lösung. Was gibt es Einfacheres als sich das Objekt einfach zu holen, da wo es gebraucht wird?

    Bsp (Klasse A, B und C brauchen das gleiche Objekt D):

    class A {
    
    void hierWirdsGebraucht() {
    D &d = D.instance();
    }
    
    }
    
    class B {
    
    void hierWirdsGebraucht() {
    D &d = D.instance();
    }
    
    }
    
    class C {
    
    void hierWirdsGebraucht() {
    D &d = D.instance();
    }
    
    }
    

    Dies ist eine sehr einfache Lösung. Sie ist sehr dynamisch, da sich der Programmierer keine Gedanken über irgendwelche Weitergaben machen muss.

    Tip:
    Laut Deiner Beschreibung erstellst Du eine GUI. Dh. unter Umständen hast Du mehrere Dialoge, die auf dem Gleichen Objekt arbeiten (im Weiteren Modell genannt). Hierzu gibt es ein pattern MVC (Modell View Controler, auch Observer genannt).

    1.) Erstelle einmal Das Modell
    2.) Erstelle (zentral) alle Dialoge
    3.) Registriere allen Dialoge die informiert werden wollen im Modell.
    Resultat: alle Dialoge die Du nutzt werden automatisch bei Änderung des Modells upgedatet.

    Gruß



  • Ein googlen nach DoModal brachte mir, dass du die mfc benutzt.Nun, das schränkt uns schonmal etwas ein. Würde sagen, ab nach mfc, da könnte dir besser geholfen werden, oder? Da kennt man sich sicher besser aus, was funktioniert und was nicht



  • sW00p schrieb:

    thx für die schnelle antwort.
    und wo muss ich dann das objekt erzeugen?

    😕
    wieso sollte das ein Problem sein ?

    struct A { // Gemeinsam zu nutzende Objekt
       A() : i(1) {}
       int i;
    };
    
    class B { // hält eine Referenz auf ein A
       A& meinA;
    public:
       B(A& a) meinA(a) {}
       void incA() {++a.i; }
    };
    
    class C { // hält einen Pointer auf ein A
       A* meinA;
    public:
       C(A* a) meinA(a) {}
       void incA() {++a->i; }
    };
    
    int main() {
       A a;
       B b(a);
       C c(&a);
       // ich kann HIER a ändern
       a.i++;
       // ... oder auch in b
       b.incA();
       // ... oder auch in c
       c.incA();
       // ... alle drei verweisen auf dasselbe A-Objekt
       return 0;
    }
    

    Ich weiß gar nicht, wieso da plötlzich singletons und Ähnliches her müssen ...

    Gruß,

    Simon2.



  • weil singleton zum einen den code kürzer und lesbarer hält und zum anderen für konsistentere beziehungen zwischen den klassen sorgt. ohne singleton schleppt jede klasse nen member mit sich rum, der da semantisch überhaupt nix zu suchen hat.

    ausserdem sorgt das singleton pattern dafür, dass garantiert zu jedem zeitpunkt immer nur exakt eine instanz des objekts bestehen kann.



  • Hi,

    natürlich hat das singleton-Pattern auch seine Berechtigung. Mir fällt aber auf, dass diese Technik oftmals als Standardlösung ins Spiel gebracht wird - auch dann, wenn Anfänger einfach fragen "Wie kann ich ein Objekt in einem anderen zugreifen ?" (gerne wird auch "Klasse" gesagt) und andere Lösungen naheliegender und passender sind.

    Mir scheint's also ob mit dem Aufschwung der singletons und statics langsam aber sicher wieder globale Variablen durch's Hintertürchen eine Renaissance feiern - und bei allen Vorteilen eben auch deren Nachteile. Sehr schön spätestens dann zu sehen, wenn das singleton dann ein Container mit möglchst unterschiedlichen Typen sein soll.

    Ob das hier der Fall ist, weiß ich nicht, aber mich wundert, dass die Form von Objektverknüpfung, die die Sprache standardmäßig anbietet, nicht mal mehr erwähnt wird ...
    IMO sollte die Herangehensweise andersherum sein: Erst mal die Aggregation, Referenz, Zeiger vorschlagen und erst wenn es wirkliche Gründe dagegen gibt, ein singleton vorschlagen (oder ein Überdenken der Anforderungen).

    Ja, es hat etwas Gutes, dass eine jede Klasse seine eigene Objektverknüpfung hat, denn die Tatsachen, dass es eine solche braucht, bedeutet noch nicht, dass alle Objekte mit demselben verknüpft werden solle/müssen. Dafür bietet die Referenz-/Pointerlösung eben BEIDES an.

    Außerdem verlangt sie vom Designer, sich gründlicher über sein Design Gedanken zu machen ... Gedanken, die jedem Projekt guttun.

    Gruß,

    Simon2.



  • Simon2 schrieb:

    sW00p schrieb:

    thx für die schnelle antwort.
    und wo muss ich dann das objekt erzeugen?

    😕
    wieso sollte das ein Problem sein ?

    struct A { // Gemeinsam zu nutzende Objekt
       A() : i(1) {}
       int i;
    };
    
    class B { // hält eine Referenz auf ein A
       A& meinA;
    public:
       B(A& a) meinA(a) {}
       void incA() {++a.i; }
    };
    
    class C { // hält einen Pointer auf ein A
       A* meinA;
    public:
       C(A* a) meinA(a) {}
       void incA() {++a->i; }
    };
    
    int main() {
       A a;
       B b(a);
       C c(&a);
       // ich kann HIER a ändern
       a.i++;
       // ... oder auch in b
       b.incA();
       // ... oder auch in c
       c.incA();
       // ... alle drei verweisen auf dasselbe A-Objekt
       return 0;
    }
    

    Ich weiß gar nicht, wieso da plötlzich singletons und Ähnliches her müssen ...

    Gruß,

    Simon2.

    ich glaub diese lösung scheint mir bisher am sinnvollsten.
    kann ich das ganze auch anstatt mit einer struktur mit einer klasse lösen?
    so dass ich die get und set methoden der member variablen direkt in klasse A schreibe?
    was ich noch nicht so ganz verstanden habe ist das hier:
    A() : i(1) {}

    @linu(x)bie:
    mehrfachvererbung geht desswegen nicht, da die objekte die ich erzeuge, schon abgeleitet sind, nämlich von CDialog.
    dem konstruktor von CDialog kann ich kann ich ja auch keine weiteren parameter mitgeben, der au das objekt verweißt oder?
    der stanadart konstuktor sieht so aus:
    CSettings_general(CWnd* pParent = NULL);

    generell wäre es ja kein problem den konstruktor auf

    CSettings_general(CWnd* pParent = NULL,CSettings* settings);

    zu ändern, meine angst ist es halt, wenn ich am standard konstruktor (der von vc++ angelegt wurde)rumpfusche, das ganze nicht mehr richtig funktioniert.



  • sW00p schrieb:

    ...
    kann ich das ganze auch anstatt mit einer struktur mit einer klasse lösen?
    ...

    Ja !
    ich schreibe hier meistens "struct", weil ich mir damit das Ganze private/public-Gedöns spare.
    Merke: "struct" = "class mit Default=public"
    Mit struct kannst Du alles machen, was Du mit einer class kannst (Memberfunktionen, Konstruktoren/Destruktoren ("Ctor/DTor"), vererben, sogar private-Bereiche definieren, ...)

    sW00p schrieb:

    ...
    A() : i(1) {}
    ...

    (Ich weiß nicht genau, was Du daran nicht verstehst, deswegen rate ich mal:)
    Einfache Initialisierungen ("i(1)") kannst Du in der sog. "Initialisierungsliste" (*) durchführen; Vorteil: Member (hier i) werden nur einmal initialisiert und bisweilen (bei Referenzen) geht es gar nicht anders.

    (*) gekennzeichnet mit einem ":" VOR dem Funktionsrumpf, also vor dem ersten "{".

    @thordk:

    sW00p schrieb:

    ...
    ich glaub diese lösung scheint mir bisher am sinnvollsten....

    :p 😉 😃

    Gruß,

    Simon2.


Anmelden zum Antworten