Problem mit verschachtelten namespace's und friend class



  • Hallöchen!

    Ich habe grade ein Problem mit verschachtelten namespace's und der friend-Definition.

    Ich habe eine Klasse ("ClassA") innerhalb eines namespaces ("space1"), die das alleinige Recht haben soll, eine Instanz einer anderen Klasse ("ClassB") zu erzeugen, welche sich in einem namespace innerhalb des namespaces ("space1::spaceInSpace1") befindet.

    Beispielhafter Code:

    //=======================================
    // Dateien der Klasse ClassA in namespace space1
    //-----------------------
    // ClassA.h
    #include "ClassB.h"
    
    namespace space1 {
    
        class ClassA {
        private:
            spaceInSpace1::ClassB* instanceOfB;
        public:
            void createInstanceOfB();
        };
    
    }
    //-----------------------
    
    //-----------------------
    // ClassA.cpp
    #include "ClassA.h"
    
    void space1::ClassA::createInstanceOfB() {
        instanceOfB = new spaceInSpace1::ClassB();
    }
    //-----------------------
    //=======================================
    
    //=======================================
    // Dateien der Klasse ClassB in namespace space1::spaceInSpace1
    //-----------------------
    // ClassB.h
    namespace space1 {
    
        namespace spaceInSpace1 {
    
            class ClassB {
                friend class ClassA;
    
            private:
                int memberVar;
    
                ClassB();
            };
    
        }
    
    }
    //-----------------------
    
    //-----------------------
    // ClassB.cpp
    #include "ClassB.h"
    
    space1::spaceInSpace1::ClassB::ClassB() {
        memberVar = 1337;
    }
    //-----------------------
    //=======================================
    

    Der Compiler (MinGW) wirft mir jedoch den Fehler entgegen, dass der Konstruktor von ClassB private ist und ich daher in ClassA::createInstanceOfB() keine Instanz von ClassB erzeugen kann.
    Ich befürchte ich habe irgendwas bei der friend-Definition falsch gemacht, aber komme auf keine Lösung 😞



  • EDIT: das ist non-standard, und funktioniert mit GCC nicht 😞 (mit anderen Compilern allerdings schon) /EDIT

    namespace space1 {
    
        class ClassA; // <- du brauchst erstmal ne fwd. declaration von space1::ClassA
    
        namespace spaceInSpace1 {
    
            class ClassB {
                // friend class ClassA; // damit sagst du: es gibt ne klasse namens ClassA im "enclosing namespace"
                                        // ("enclosing" bezieht sich auf ClassB, "enclosing namespace" wäre also space1::spaceInSpace1),
                                        // und die ist mein freund. also nicht das was du willst
    
                friend ClassA; // <- ohne "class". damit sagst du "das was ClassA heisst und im aktuellen scope erreichbar ist
                               // ("im aktuellen scope erreichbar" impliziert dass es bereits bekannt sein muss, daher brauchen wir die fwd. declaration),
                               // ist mein freund". also genau das was du willst.
    
            private:
                int memberVar;
    
                ClassB();
            };
    
        }
    
    }
    


  • mh...

    also meine Dateien sehen nun wie folgt aus:

    // ClassA.h
    #ifndef __CLASSA_H__
    #define __CLASSA_H__
    
    #include "ClassB.h"
    
    namespace space1 {
    
        class ClassA {
        private:
            spaceInSpace1::ClassB* instanceOfB;
        public:
            void createInstanceOfB();
        };
    
    }
    
    #endif
    
    // ClassA.cpp
    #include "ClassA.h"
    
    void space1::ClassA::createInstanceOfB() {
        instanceOfB = new spaceInSpace1::ClassB();
    }
    
    // ClassB.h
    #ifndef __CLASSB_H__
    #define __CLASSB_H__
    
    namespace space1 {
    
        class ClassA; // <- du brauchst erstmal ne fwd. declaration von space1::ClassA
    
        namespace spaceInSpace1 {
    
            class ClassB {
                // friend class ClassA; // damit sagst du: es gibt ne klasse namens ClassA im "enclosing namespace"
                                        // ("enclosing" bezieht sich auf ClassB, "enclosing namespace" wäre also space1::spaceInSpace1),
                                        // und die ist mein freund. also nicht das was du willst
    
                friend ClassA; // <- ohne "class". damit sagst du "das was ClassA heisst und im aktuellen scope erreichbar ist
                               // ("im aktuellen scope erreichbar" impliziert dass es bereits bekannt sein muss, daher brauchen wir die fwd. declaration),
                               // ist mein freund". also genau das was du willst.
    
            private:
                int memberVar;
    
                ClassB();
            };
    
        }
    
    }
    
    #endif
    
    // ClassB.cpp
    #include "ClassB.h"
    
    space1::spaceInSpace1::ClassB::ClassB() {
        memberVar = 1337;
    }
    

    Und nun spuckt mir MinGW folgenden Fehler aus:

    ClassB.h (Line 16): error: a class-key must be used when declaring a friend
    ClassB.h (Line 16): error: friend declaration does not name a class or function
    


  • Mist.
    Sieht so aus als hätte ich mir da nonstandard-Verhalten von MSVC angewöhnt.

    Das "class" an der Stelle ist wirklich vom Standard vorgeschrieben - wusste ich nicht.
    Dummerweise weiss ich nicht wei man dann eine friend Declaration machen soll, wenn der friend in einem anderen Namespace lebt...

    EDIT: probier mal friend class space1::ClassA; .



  • Yeah, jetzt gehts!
    Dann war meine erste Idee, space1::ClassA zu nutzen, doch nicht falsch. Wusste bloß nicht, dass man dann ClassA innerhalb von ClassB.h auch noch deklarieren muss.

    Danke für die Unterstzütung 🙂


Anmelden zum Antworten