Problem mit friend-classes



  • Hi,

    ich habe in meinem Projekt für jede Klasse eine eigene Datei die jeweils
    einen "Guard" am Anfang des Headers haben:

    #ifndef __TESTCLASS1_H__
    #define __TESTCLASS1_H__
    
    /* class TestClass1 { ... } */
    
    #endif
    

    Nun habe ich einige Klassen, die sich beide 'kennen' sollen bzw. die jeweils einen Pointer auf ein Objekt der anderen Klasse haben:

    // TestClass1.hpp
    class TestClass1
    {
        TestClass2* Member;
    };
    
    // TestClass2.hpp
    class TestClass2
    {
        TestClass1* Member;
    };
    

    Jetzt sollen diese auch noch beide Freunde sein (mit "friend class ...").
    Allerdings kann ich ja nicht einfach in beiden Dateien die jeweils andere inkluden, sonst wäre das ja eine Endlosschleife:

    // TestClass1.hpp
    #include "TestClass2.hpp"
    // ...
    
    // TestClass2.hpp
    #include "TestClass1.hpp"
    // ...
    

    Also habe ich einfach nur jeweils die andere Klasse deklariert (mit "class TestClass1;").
    Jetzt meckert aber der Kompiler immer noch, dass die Members der anderen Klasse privat oder eben geschützt seien.

    Wie kann ich das Problem beheben? Vielleicht ist ja der Compiler mit der Deklaration nicht einverstanden?!

    Ich hatte solche Probleme schon öfters, aber diesmal weiß ich einfach nicht was ich falsch mache 😞

    Danke schonmal im Voraus. 🙂



  • So viel ich weiß muss die Klasse bei friend class ... weder definiert noch deklariert sein.



  • Wenn du in Klasse A einfach ein "friend class B" schreibst reicht das vollkommen aus, ohne dass du B vorher irgendwie erwähnt haben müsstest. Du kannst per friend-Deklaration gleichzeitig eine völlig neue Klasse deklarieren (aber nicht definierern).



  • Achso, vielleicht habe ich dadurch ja eine falsche friend-Deklaration geschrieben.
    Ich habe bei meinem Klassen immer noch sowas wie "APP_EXPORT" welches ~ so definiert ist:

    // Globals.hpp
    #ifdef __EXPORT_TO_LIBRARY__
    #    if defined(WIN32)
    #        define APP_EXPORT __declspec(dllexport)
    #    elif defined(__linux__)
    #        define APP_EXPORT
    #    endif
    #else
    #    define APP_EXPORT
    #endif
    
    // ClassA.hpp
    class APP_EXPORT ClassA { /* ... */ };
    
    // ClassB.hpp
    class APP_EXPORT ClassB
    {
        friend ClassA;            // So? ...
        friend APP_EXPORT ClassA; // ... oder so?
    };
    


  • Hier habe ich ein Beispiel wie es bei mir aussieht, ihr könnt versuchen das zu kompilieren. Und hier tritt genau der gleiche Fehler auf.
    Ich habe das Problem unter Linux genau so wie unter Windows:

    #include <cstdlib>
    
    namespace space1
    {
    
    class ClassA
    {
        int Data;
        ClassA();
    };
    
    }
    
    namespace space1
    {
    namespace space2
    {
    
    class ClassB
    {
        friend class ClassA;
        int Data;
        ClassB() : Data(0)
        {
        }
    };
    
    }
    }
    
    namespace space1
    {
    
    ClassA::ClassA()
    {
        space2::ClassB Obj;
        Data = Obj.Data;
    }
    
    }
    
    int main()
    {
        return 0;
    }
    


  • Also das kompiliert bei mir ohne Probleme. (VS 2008).

    Zeig mal den genauen Fehler.

    Du hast hier bei den Klassen nämlich keine public Spezifizierer und somit ist auch der Konstruktor privat.. So kannst du kein Objekt erstellen. 😉

    EDIT:
    Worauf du auch noch achten musst ist, dass du die Memberfunktionen nicht im Header implementieren darfst, weil sonst (wenn du die andere Klasse brauchst) natürlich die genaue Implementierung bekannt sein muss.



  • Ich hab GCC 4.x unter Linux aber unter Windows habe ich mit dem GNU C++ Compiler das selbe Problem.

    29    Fehler: >>int space1::space2::ClassB::Data<< ist privat
    44    Fehler: in diesem Zusammenhang
    


  • Beachte die namespaces. Eine friend-Deklaration deklariert die Klasse im umgebenden Namensraum. D.h. du deklarierst space2::ClassA als friend, die du garnicht definierst.


Anmelden zum Antworten