Problem bei der Deklaration von Klassen



  • Hallo, ich bin eher in der Java-Ecke beheimatet und habe ein Problem bei der Deklaration der folgenden C++ Klassen:

    class Test1 {
      public:
        void doSomething(Test2 o);
    };
    
    class Test2 {
      public:
        virtual void updateSomething(Test1 o);
    };
    

    Der Compiler meldet (verständlicherweise), dass Test2 bei der Deklaration der Methode doSomething noch nicht deklariert sei. Wie kann ich das umgehen?

    Das Ziel wäre eigentlich, Test2 wie ein Interface in Java zu verwenden.

    Danke für eure Antworten!



  • Forward Deklaration.

    class Test2;//<----
    
    class Test1 {
      public:
        void doSomething(Test2 o);
    };
    
    class Test2 {
      public:
        virtual void updateSomething(Test1 o);
    };
    

  • Administrator

    Firefighter schrieb:

    Forward Deklaration.

    Bringt dir nichts, wenn er ein ganzes Objekt übergeben will. Forward Deklaration hilft nur bei Zeigern und Referenzen.

    @jaron,
    Dafür gibt es grundsätzlich keine Lösung, ausser du schreibst die Signatur der Funktion ein wenig um und teilst Definition und Deklaration der Klassen auf. Also ca. so:
    Test1.hpp

    #ifndef INCLUDE_GUARD_TEST1
    #define INCLUDE_GUARD_TEST1
    
    class Test2; // <- forward declaration
    
    class Test1 {
      public:
        void doSomething(Test2 const& o); // eine Referenz auf ein konstantes Objekt übergeben,
                                          // die Kopie wird in der Definition durchgeführt.
    };
    
    #endif // INCLUDE_GUARD_TEST1
    

    Test1.cpp

    #include "Test1.hpp"
    #include "Test2.hpp"
    
    void Test1::doSomething(Test2 const& o)
    {
      // mach was damit, oder erstell eine Kopie:
      Test2 copy = o;
    }
    

    Test2.hpp

    #ifndef INCLUDE_GUARD_TEST2
    #define INCLUDE_GUARD_TEST2
    
    #include "Test1.hpp"
    
    class Test2 {
      public:
        virtual void updateSomething(Test1 o);
    };
    
    #endif // INCLUDE_GUARD_TEST2
    

    Test2.cpp

    #include "Test2.hpp"
    
    void Test2::updateSomething(Test1 o)
    {
      // ...
    }
    

    Das ganze dann natürlich über Makefile & Linker zusammenfügen. Wenn du eine vernünftige IDE hast, geschieht dies automatisch.

    Referenzen auf konstante Objekte zu übergeben ist meistens sehr praktisch, vor allem wenn das Objekt gross ist. Somit wird eine unnötige Kopie vermieden, wenn sie nicht benötigt wird.

    Stichwörter welche du dir anschauen solltest:
    - Include Guards
    - Forward Declaration
    - Const correctness

    Und noch ein Tipp:
    Probier unter C++ nicht Java zu programmieren. C++ und Java sind komplett verschiedene Sprachen. Nicht mal die Syntax stimmt wirklich ganz überein. Mit Java Lösungen ist man in C++ schlecht bedient, man löst Probleme anders.

    Grüssli



  • Nur bei Zeigern und Referenzen? Ok war mir nicht bekannt, danke für die Ergänzung.



  • Bringt dir nichts, wenn er ein ganzes Objekt übergeben will. Forward Deklaration hilft nur bei Zeigern und Referenzen.

    Nope. Weit verbreiteter Irrtum. Das geht.

    class A;
    
    class foo
    {
    public:
    	A bar ( A a );
    };
    
    class A
    {
    };
    
    A foo::bar ( A a)
    { return a; }
    
    int main ()
    {	
    	foo f;
    	A a;
    
    	f.bar ( a );
    }
    

    Kein Problem. Wie man sieht, geht es auch mit dem Rückgabewert.



  • Wo es nicht geht, ist bei Membervariablen, weil dort die Grösse des Objekts bei der Deklaration bekannt sein muss und deshalb eine Vorwärtsdeklaration nicht ausreicht.



  • Nexus schrieb:

    Wo es nicht geht, ist bei Membervariablen, weil dort die Grösse des Objekts bei der Deklaration bekannt sein muss und deshalb eine Vorwärtsdeklaration nicht ausreicht.

    Und Vererbung.



  • Danke für die Antworten.

    Wie bereits erwähnt, hat die in der ersten Antwort erwähnte Forward Declaration funktioniert.

    Nach einer sehr langen Absenz taste ich mich langsam wieder an C++ heran. Da es sich um die Programmierung eines Arduino (Mikrocontroller) handelt, verfüge ich nicht über den ganzen Sprachumfang von C++ und es ist mir auch klar, dass mein Code weder effizient noch C++ konform ist. Ich arbeite daran. Schritt für Schritt.



  • Dravere schrieb:

    ...Bringt dir nichts, wenn er ein ganzes Objekt übergeben will...

    Glaube ich gar nicht al, denn er schrieb:

    jaron schrieb:

    ...ich bin eher in der Java-Ecke beheimatet ...

    Da wird er vermutlich an Referenzen als Parameter gedacht und nur das "&" vergessen haben.

    Gruß,

    Simon2.


  • Administrator

    @drakon,
    Danke! Wollte es gar nicht glauben, habe es mit allen Kompilern getestet, welche mir zur Verfügung stehen, funktioniert aber mit allen. Und im Standard steht es sogar, dass erst bei der Definition der Funktion die Typen vollständig bekannt sein müssen. Man lernt nie aus 😃

    @Simon2,
    Das ist eine Vermutung, aber im Code steht es anders und ich habe mich auf die Lösung von Firefighter bezogen. Firefighter hat nämlich auch keine Referenz verwendet. Und da wusste ich ja noch nicht, dass sowas auch geht 😉

    Grüssli


Anmelden zum Antworten