Gegenseitige Includes = Zwingende Designänderung?



  • Hi..

    Wie ist es eigentlich, wenn sich zwei Header gegenseitig inkludieren können sollen (Mit Klassen zB.)?
    Wenn man #pragma once nutzt, dann wird eines der beiden Includes doch ignoriert, nicht? Also bringt es dann höchstens so viel wie eine forward declaration?
    Und ohne #pragma once gibt's nen endlos-Inkludieren -> compiler-error.

    Hat man immer ein schlechtes Design, wenn sich zwei Header gegenseitig inkludieren müssen?

    Manchmal reicht ja auch ne forward declaration, aber nicht wenn man zB. auch Methoden eines Klassenobjekts ansprechen will..?!

    Ich erinnere mich an früher, da hatte ich immer dieses Problem, und heutzutage hoffe ich immer darauf, dass so eine Situation nicht vorkommt, wobei das für mich nicht immer einfach ist...

    😕



  • Erkenner schrieb:

    Hat man immer ein schlechtes Design, wenn sich zwei Header gegenseitig inkludieren müssen?

    Ja.

    Erkenner schrieb:

    Manchmal reicht ja auch ne forward declaration, aber nicht wenn man zB. auch Methoden eines Klassenobjekts ansprechen will..?!

    Will man eigentlich nicht, zumindest nicht im Header. Dort reicht es, den Typ zu deklarieren.

    // =============== A.hpp ===============
    class B;
    
    class A
    {
        public:
            void GreifeAufBZu();
        private:
            B* ZeigerAufB;
    };
    
    // =============== A.cpp =============== 
    #include "A.hpp" 
    #include "B.hpp" // <- erst hier
    
    void A::GreifeAufBZu()
    {
        ZeigerAufB->MacheWas(*this);
    }
    
    // =============== B.hpp ===============
    class A;
    
    class B
    {
        public:
            void MacheWas(A a);
            A MacheWasAnderes(const A& a);
    };
    
    // =============== B.cpp ===============
    #include "B.hpp"
    #include "A.hpp" // <- erst hier
    
    void B::MacheWas(A a);
    {
        // hier a benutzen
    }
    
    A B::MacheWasAnderes(const A& a)
    {
        // hier a benutzen und 
        // etwas zurückgeben
    }
    


  • Hehe. Langsam denke ich wirklich, dass es sich gelohnt hat den Beitrag zu schreiben:

    Gleich der erste: (17.10.09)
    Definitionen und Deklarationen in C++
    http://drakon.ch/



  • Hallo alle miteinander,

    Ich hatte das selbe Problem wie Erkenner; eure Lösungen haben das Problem an sich gelöst. Allerdings erhielt ich dadurch mehrere Fehler vom Typ LNK2005, nämlich:

    1>Snake.obj : error LNK2005: "public: void __thiscall CSnake::Init(int,int,float)" (?Init@CSnake@@QAEXHHM@Z) ist bereits in Item.obj definiert.
    1>Snake.obj : error LNK2005: "public: void __thiscall CSnake::Render(void)" (?Render@CSnake@@QAEXXZ) ist bereits in Item.obj definiert.
    1>Snake.obj : error LNK2005: "public: void __thiscall CSnake::Update(void)" (?Update@CSnake@@QAEXXZ) ist bereits in Item.obj definiert.
    1>Snake.obj : error LNK2005: "private: void __thiscall CSnake::GetKeyState(void)" (?GetKeyState@CSnake@@AAEXXZ) ist bereits in Item.obj definiert.
    1>Snake.obj : error LNK2005: "public: bool __thiscall CSnake::CompareRects(struct SDL_Rect,int)" (?CompareRects@CSnake@@QAE_NUSDL_Rect@@H@Z) ist bereits in Item.obj definiert.
    1>Snake.obj : error LNK2005: "public: void __thiscall CSnake::NewItem(int)" (?NewItem@CSnake@@QAEXH@Z) ist bereits in Item.obj definiert.
    1>Item.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: void __thiscall CItem::Init(int,class CSnake *)" (?Init@CItem@@QAEXHPAVCSnake@@@Z)".
    1>Snake.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: void __thiscall CItem::Init(int,class CSnake *)" (?Init@CItem@@QAEXHPAVCSnake@@@Z)".
    1>C:\Dokumente und Einstellungen\Tobi\Eigene Dateien\Visual Studio 2008\Projects\Snake2\Debug\Snake2.exe : fatal error LNK1120: 1 nicht aufgelöste externe Verweise.
    

    Kann mir jemand sagen, was diesen Fehler hervorruft? Die Antworten in der msdn waren mir ehrlichgesagt zu hoch... Ich bin noch ein ziemlicher Anfänger.

    Gruß
    Royal



  • Jopp, du hast die include-guards vergessen(LNK2005)
    Und dann auch noch vergessen, Fkt zu definieren(LNK2001)

    bb



  • Meinst du mit includeguards:

    #ifndef BLA
    #define BLA
    (Code)
    #endif
    

    Wenn ja, hab ich das in jeder hpp gemacht.

    Und was ist Fkt?



  • Royal_Flush schrieb:

    Und was ist Fkt?

    Funktion(en). unskilled ist manchmal etwas wortkarg. 😉

    1>Item.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: void __thiscall CItem::Init(int,class CSnake *)" (?Init@CItem@@QAEXHPAVCSnake@@@Z)".
    1>Snake.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: void __thiscall CItem::Init(int,class CSnake *)" (?Init@CItem@@QAEXHPAVCSnake@@@Z)".

    Hier steht, dass die Funktionsdefinition zu CItem::Init(int, CSnake*) fehlt.

    Zu dem anderen Fehler: Das liegt wahrscheinlich daran, dass gewisse Funktionsdefinitionen im Header stehen und so mehrfach vorhanden sind, was zu einem Fehler führt. Schau doch mal drakons Link an...



  • Wenn ich das richtig verstanden habe, soll ich also alle Definitionen in die cpp schreiben? Einzeiler habe ich nämlich sonst immer gleich definiert... Interessanterweise bewwirkt die Auslagerung in die cpp genau das Gegenteil. Alle Funktionen, die in der cpp (Snake.cpp) definiert werden anstatt im Header, rufen den LNK2005 hervor, wohingegen im Header definierte Funktionen fehlerfrei kompiliert zu werden scheinen. Das verwirrt mich jetzt enorm.



  • Nexus schrieb:

    Royal_Flush schrieb:

    Und was ist Fkt?

    Funktion(en). unskilled ist manchmal etwas wortkarg. 😉

    bin ich? :< ^^
    sry - dachte, das wäre offensichtlich

    Nexus schrieb:

    Zu dem anderen Fehler: Das liegt wahrscheinlich daran, dass gewisse Funktionsdefinitionen im Header stehen und so mehrfach vorhanden sind, was zu einem Fehler führt. Schau doch mal drakons Link an...

    oh ja, sry - die fehlermeldung hätte bei fehlenden include-guards anders gelautet^^

    bb



  • So hat sich erledigt. Ich hab mich vertippt. Ich hab die Snake.cpp anstatt der Snake.hpp eingebunden. 😃

    Also, danke für eure Hilfe.


Anmelden zum Antworten