Zwei Klassen verbinden?



  • Hey,
    Ich habe eine wahrscheinlich recht blöde Frage.
    Also wie kann ich 2 Klassen verbinden?
    Ich will nicht vererben sondern ich mochte das beide Klassen auf die jeweiligen Methoden der anderen zugreifen können.
    Es geht darum das KlasseA die Oberfläche ist und KlasseB die Steuerung.
    Diese sollte ja rein von der Logik her bidirektional verbunden sein.

    In meinem Porgramm läuft das so:

    In der Main wird ein Objekt der GUI erstellt und in der GUI dann ein Objekt der
    Steuerung. Somit kennt die GUI schon mal die Steuerung.
    Aber wie kann ich der Steuerung jetzt sagen was die gui ist?
    Also welches Objekt. Ich habe versucht es im Konstruktor zu übergeben,
    was aber leider überhaupt nicht funktioniert hat. (Die Klasse wurde nicht als
    Datentyp anerkannt)

    Könnt ihr mir helfen?



  • gosch00 schrieb:

    Also wie kann ich 2 Klassen verbinden?

    Indem du jede Klasse jeweils Methoden der anderen aufrufen lässt.

    gosch00 schrieb:

    Ich habe versucht es im Konstruktor zu übergeben,
    was aber leider überhaupt nicht funktioniert hat. (Die Klasse wurde nicht als
    Datentyp anerkannt)

    Kannst du diesbezüglich etwas konkreter werden? Ein kurzer, problembezogener Code und die exakte Fehlermeldung wären hilfreich. Der entsprechende Header ist in der .cpp-Datei schon eingebunden, oder?



  • Erstmal code:

    #include <iostream>
    #include "KlasseB.h"
    
    using namespace std;
    
    class KlasseA {
    public:
        KlasseA();
        virtual ~KlasseA();
    private:
        KlasseB* b;
    
    };
    
    #include "KlasseA.h"
    
    KlasseA::KlasseA() {
        cout << "Klasse A erstellt!" << endl;
        b = new KlasseB(this);
    }
    
    KlasseA::~KlasseA() {
        cout << "Klasse A zerstört!" << endl;
    }
    
    #include <iostream>
    #include "KlasseA.h"
    
    using namespace std;
    
    class KlasseB {
    public:
        KlasseB(KlasseA p);
        virtual ~KlasseB();
    private:
        KlassA* A;
    
    };
    
    #include "KlasseB.h"
    
    KlasseB::KlasseB(KlasseA p) {
        cout << "Klasse B erstellt!" << endl;
        A=p;
    }
    
    KlasseB::~KlasseB() {
        cout << "Klasse B zerstört!" << endl;
    }
    

    So soll das im groben Funktionieren.
    Ist das Problem vielleicht das das ich Klasse B in Klasse A erstelle?
    Und dann übergeben will?
    Lasse ich die übergabe nämlich weg und lasse nur die GUI die Steuerung kennen funktioniert es.



  • Diese Frage wird ca. jeden Tag gestellt. Darum fühle ich mich einmal wieder genötigt dich auf diesen Artikel hier hinzuweisen:
    http://www.drakon.ch/?id=&offset=3&mobile=0&show_entry=77

    Kurz:
    Das, was du da machst ergibt zyklische Abhängigkeiten und muss mit Vorwärtsdeklarationen umgangen werden (näheres dazu im Artikel).

    btw:

    using namespace std;
    

    Das ist im Header nicht gut. Überleg mal was passiert, wenn jemand anderst deinen Header einbindet und zufälligerweise z.B eine eigene Klasse string hat. (gibt einen Namenskonflikt mit std::string..)



  • Da gibts mehrere Probleme bzw. Unschönheiten.

    1) Du kannst nicht zwei Dateien sich gegenseitig einbinden lassen. Das würde zu einer Endlosrekursion führen. Deshalb solltest du mit Vorwärtsdeklarationen arbeiten:

    // KlasseA.h
    class B; // <- Vorwärtsdeklaration
    
    class A
    {
        // ...
    };
    
    // KlasseB.h
    class A;
    
    class B
    {
        // ...
    };
    

    2) Gibt es einen Grund, warum du eine Kopie statt eines Zeigers oder einer Referenz übergibst? Warum nicht eines davon (wenn möglich mit const ):

    KlasseB(KlasseA& p);
    KlasseB(KlasseA* p);
    

    3) Benutze NIE NIE NIE using namespace in Headerdateien. Dadurch wird nämlich der ganze Namensraum für alle inkludierenden Dateien ausgeleert. Auf diese Weise sind Namensräume äusserst sinnlos.

    4) Benutze für Konstruktoren Initialisierungslisten statt Zuweisungen. Folgendes

    KlasseB::KlasseB(KlasseA* p)
    {
        A = p;
    }
    

    wird zu

    KlasseB::KlasseB(KlasseA* p) : A(p)
    {
    }
    

    5) Ich sehe keinen Grund, warum die Destruktoren virtuell sind. Falls du die Klassen nicht polymorph benutzt, verzichte auf virtual . Nur weil du sowas später in Betracht ziehen könntest, musst du das noch nicht jetzt tun.

    Selbst wenn andere Klassen von KlasseA bzw. KlasseB erben, ist das noch kein Grund für einen virtuellen Destruktor. Du brauchst virtuelle Funktionen wirklich nur, wenn du Objekte abgeleiteter Klassen über einen Zeiger oder eine Referenz auf die Basisklasse ansprechen willst.

    6) Halte Abhängigkeiten klein. Inkludiere Headerdateien nur, falls wirklich nötig, und tu das so spät wie möglich. <iostream> muss erst in den .cpp-Dateien bekannt sein, also reicht ein #include dort.


Anmelden zum Antworten