Problem bei Zugriff auf eine Funktion einer anderen Klasseninstanz



  • Hallo,
    ich habe in meinem MainWindow Konstruktor u.a. zwei Klasseninstanzen, nämlich FMC* fmc und Current* current. fmc benötigt Zugriff auf current, also habe ich im MainWindow mit

    fmc = new FMC(current);
    

    Current* current übergeben. Es funktioniert bisher alles, jedoch brauche ich für current jetzt auch zusätzlich Schreibzugriff auf eine bestimmte Funktion von fmc. Da ich aber mein current vor fmc im MainWindow-Konstruktor erstellt habe, kann ich ja nicht in der Zeile von Current die nicht bekannte Instanz fmc übergeben. Wie kann ich diesen einen Zugriff ermöglichen?
    Current soll mit

    fmc->SetScratchpad("ENTER INERTIAL POSITION");
    

    auf

    void FMC::SetScratchpad(QString q)
    {
    	scratchpad = q;
    }
    

    zugreifen, wobei SetScratchpad() public ist.
    Ich habe keine konkrete Lösung gefunden bzw. die Vorgehensweise mit std::bind funktioniert hier (angepasst) nicht, wie sie von euch in einem anderen Thread von mir für etwas anderes vorgestellt wurde. Könntet ihr mir bitte helfen, eine Lösung zu finden?
    Grüße
    Stefan



  • Du solltest keine Klassen haben, die sich gegenseitig aufrufen!
    Da du ja mit Qt arbeitest, erstelle entweder ein eigenes Signal und binde daran oder versuche das Design (sowie den Ablauf) so zu ändern, daß es nicht mehr nötig ist.



  • @Th69 sagte in Problem bei Zugriff auf eine Funktion einer anderen Klasseninstanz:

    Du solltest keine Klassen haben, die sich gegenseitig aufrufen!

    Und was wäre daran fürs Programmieren so schlimm wenn man es trotzdem an manchen Stellen so macht?

    Da du ja mit Qt arbeitest, erstelle entweder ein eigenes Signal und binde daran oder versuche das Design (sowie den Ablauf) so zu ändern, daß es nicht mehr nötig ist.

    Die beiden Klassen FMC und Current sind keine QWidgets o.ä., sondern der QString des SetScratchpad() wird als solcher in einem Widget PaintCDU() mittels QPainter angezeigt. Somit fällt für diesen Fall das Qt-Signal-Slot Prinzip m.M.n. weg.
    Wie könnte denn das "Design" oder der "Ablauf" generell besser geplant werden?

    Edit: bzw. wie entscheidet man, was man in eine Klasse packt und was man besser trennt?



  • @stefanpc81 sagte in Problem bei Zugriff auf eine Funktion einer anderen Klasseninstanz:

    @Th69 sagte in Problem bei Zugriff auf eine Funktion einer anderen Klasseninstanz:

    Du solltest keine Klassen haben, die sich gegenseitig aufrufen!

    Und was wäre daran fürs Programmieren so schlimm wenn man es trotzdem an manchen Stellen so macht?

    Weil man dadurch dann eine enge Kopplung zwischen diesen Klassen hat (und wie du schon erkannt hast, ist die Initialisierung dadurch schwieriger).
    Dann stellt sich auch die Frage, warum ist das dann nicht eine Klasse?

    Du könntest zwar eine zusätzliche Setter-Methode Current::SetFMC(FMC *fmc) erstellen, aber das erhöht ja die Abhängigkeit.

    Da du ja mit Qt arbeitest, erstelle entweder ein eigenes Signal und binde daran oder versuche das Design (sowie den Ablauf) so zu ändern, daß es nicht mehr nötig ist.

    Die beiden Klassen FMC und Current sind keine QWidgets o.ä., sondern der QString des SetScratchpad() wird als solcher in einem Widget PaintCDU() mittels QPainter angezeigt. Somit fällt für diesen Fall das Qt-Signal-Slot Prinzip m.M.n. weg.

    Solange die Klassen von QObject abgeleitet sind, kann man das Qt Signal-Slot-Prinzip nutzen (abhängig von Qt ist die Klasse ja schon, wenn du QString als Parameter benutzt).

    Wie könnte denn das "Design" oder der "Ablauf" generell besser geplant werden?

    Edit: bzw. wie entscheidet man, was man in eine Klasse packt und was man besser trennt?

    Ich persönlich erstelle mir immer eine hierarchische Projektstruktur, so daß also untergeordnete Klassen niemals direkt auf übergeordnete zugreifen.

    Falls dann doch ein indirekter Zugriff erfolgen soll, verwende ich in C# dafür Ereignisse (events) und Schnittstellen (interfaces).
    In C++ also Callbacks (bzw. Signal-Slot) sowie abstrakte Klassen.



  • Hallo @stefanpc81,
    Auf Deine Aussage "kann ich ja nicht in der Zeile von Current die nicht bekannte Instanz fmc übergeben. Wie kann ich diesen einen Zugriff ermöglichen?" gibt es meiner Meinung schon eine Antwort.
    Du kannst in den Headern (.h) von zwei Klassen jeweils die einer der anderen durch forward declaration bekannt machen. In der jeweiligen Source (.cpp) includest Du dann zusätzlich die Header der forward deklarierte Klasse.
    Hier mal ein ganz kleines Beispiel mit Pointern!!! Würde ich nicht so lösen, sondern mindesten mit std::shared_ptr; aber dann müsste ich eine Löschlogik einbauen.

    Test1.h

    #ifndef INC_TEST1_H
    #define INC_TEST1_H
    // Forward
    class Test2;
    
    class Test1
    {
      private:
        Test2 * m_pTest2;
      public:
        Test1( Test2 * pTest2 = nullptr );
        void setTest2( Test2 * pTest2 );
    };
    #endif
    

    Test1.cpp

    #include "Test1.h"
    #include "Test2.h"
    Test1::Test1( Test2 * pTest2 )
      : m_pTest2( pTest2 )
    {
    }
    void Test1::setTest2( Test2 * pTest2 )
    {
      m_pTest2 = pTest2;
    }
    

    Test2.h

    #ifndef INC_TEST2_H
    #define INC_TEST2_H
    // Forward
    class Test1;
    
    class Test2
    {
      private:
        Test1 * m_pTest1;
      public:
        Test2( Test1 * pTest1 = nullptr );
        void setTest1( Test1 * pTest1 );
    };
    #endif
    

    Test2.cpp

    #include "Test2.h"
    #include "Test1.h"
    Test2::Test2( Test1 * pTest1 )
      : m_pTest1( pTest1 )
    {
    }
    void Test2::setTest1( Test1 * pTest1 )
    {
      m_pTest1 = pTest1;
    }
    

    main.cpp

    #include "Test1.h"
    #include "Test2.h"
    int main(int argc, char *argv[])
    {
      Test1 * t_pTest1 = new Test1;
      Test2 * t_pTest2 = new Test2( t_pTest1 );
    
      t_pTest1->setTest2( t_pTest2 );
    
      delete t_pTest1;
      delete t_pTest2;
      return 0;
    }
    

    Wenn Du mit Zeigern arbeitest, sei Dir der Problematik der gegenseitigen Referenzierung bewust. Wer löscht wen?
    Gruß Helmut