Namespace Probleme



  • Hi,

    eigentlich sind ja Namespaces dazu dar, eine Bibliothek von einer anderen zu trennen, damit keine Namenskonflikte auftreten.

    Ich habe eine Klasse in einem Namespace a.
    Dann noch eine Klasse im Namspace b, der liegt im Namespace a.
    Jetzt habe ich in beiden Namespaces eine Klasse mit dem selben Namen definiert.
    Ich benutze keine using-Direktiven.

    Jetzt bekomm ich trotzdem für jede Methode und jedem Konstruktor, die in beiden Klassen identisch sind:

    error: multiple definition of a::classname::methname' error: undefined reference toa:🅱:classname::methname'

    Also "klaut" die Klasse aus Namespace a die Methoden der Klasse aus Namespace a::b und hat dann 2 Methoden, was zu dem Linker-Error führt.

    Wie kann ich das ändern? Ich will die Klasse nicht umbenennen.



  • Ein Minimalbeispiel, welches den Fehler reproduziert. Ich weiß ja nicht was du da gemacht hast... Ich habe mit sowas keine Probleme:

    //test.h
    #ifndef TEST_H_A
    #define TEST_H_A
    
    namespace a
    {
    	class A
    	{
    	public:
    		void foo();
    	};
    
    	namespace b
    	{
    		class B
    		{
    		public:
    			void foo();
    		};
    	}
    }
    
    #endif
    
    //test.cpp
    #include "test.h"
    
    void a::A::foo(){}
    void a::b::B::foo(){}
    


  • > Wie kann ich das ändern? Ich will die Klasse nicht umbenennen.

    Zeig ein kompilierbares Mimimalbeispiel, was zu denselben Linkerfehlern führt. (Das ist Dein Job als Hilfesuchender).



  • Okay, die undefined references sind jetzt weg, aber das Grundproblem ist das gleiche.

    // main.cpp
    int main(int, char**) {
        return 0;
    }
    
    // test_class.h
    #ifndef TEST_CLASS_H
    #define TEST_CLASS_H
    
    namespace a {
        class test_class {
        public:
            test_class();
            virtual ~test_class();
    
            int foo();
        };
    }
    
    #endif // TEST_CLASS_H
    
    // test_class.cpp
    #include "test_class.h"
    
    namespace a {
        test_class::test_class() {
        }
    
        test_class::~test_class() {
        }
    
        int test_class::foo() {
            return 0;
        }
    }
    
    // ordner/test_class.h
    #ifndef ORDNER_TEST_CLASS_H
    #define ORDNER_TEST_CLASS_H
    
    namespace a {
        namespace b {
            class test_class {
            public:
                test_class();
                virtual ~test_class();
            };
        }
    }
    
    #endif // ORDNER_TEST_CLASS_H
    
    // ordner/test_class.cpp
    #include "test_class.h"
    
    namespace a {
        namespace b {
            test_class::test_class() {
            }
    
            test_class::~test_class() {
            }
        }
    }
    

    Die zweite Klasse ist ein einem Überordner.

    Das ist das Ergebnis:

    /home/henning/Dokumente/Projekte/untitled-build-desktop/../untitled/ordner/test_class.cpp:5: multiple definition of a::b::test\_class::test_class()' test\_class.o:/home/henning/Dokumente/Projekte/untitled-build-desktop/../untitled/ordner/test\_class.cpp:5: first defined here test\_class.o: In functiontest_class':
    /home/henning/Dokumente/Projekte/untitled-build-desktop/../untitled/ordner/test_class.cpp:5: multiple definition of a::b::test\_class::test_class()' test\_class.o:/home/henning/Dokumente/Projekte/untitled-build-desktop/../untitled/ordner/test\_class.cpp:5: first defined here test\_class.o: In function~test_class':
    /home/henning/Dokumente/Projekte/untitled-build-desktop/../untitled/ordner/test_class.cpp:8: multiple definition of a::b::test\_class::~test_class()' test\_class.o:/home/henning/Dokumente/Projekte/untitled-build-desktop/../untitled/ordner/test\_class.cpp:8: first defined here test\_class.o: In function~test_class':
    /home/henning/Dokumente/Projekte/untitled-build-desktop/../untitled/ordner/test_class.cpp:8: multiple definition of a::b::test\_class::~test_class()' test\_class.o:/home/henning/Dokumente/Projekte/untitled-build-desktop/../untitled/ordner/test\_class.cpp:8: first defined here test\_class.o: In function~test_class':
    /home/henning/Dokumente/Projekte/untitled-build-desktop/../untitled/ordner/test_class.cpp:8: multiple definition of `a:🅱:test_class::~test_class()'
    test_class.o:/home/henning/Dokumente/Projekte/untitled-build-desktop/../untitled/ordner/test_class.cpp:8: first defined here
    collect2: ld returned 1 exit status
    make: *** [untitled] Fehler 1



  • Deine Fehlermeldungen kann ich nicht reproduzieren. Ich sehe auch keine Fehler im Quelltext. Ist alles so, wie es sein soll. Da hast Du wohl irgendwo einen anderen Fehler gemacht. Vielleicht überschreibst Du versehentlich eine Objekt-Datei beim Kompilieren. Es fallen ja zwei Übersetzungseinheiten an, die man beide test_class.o nennen könnte. Wenn Du die .o-Files in ein einziges Verzeichnis ohne Unterordner packst, überschreibst Du das eine mit dem anderen. Das würde dann aber eher zu "undefined reference" statt "multiple definition" führen.

    Bei mir geht's fehlerfrei:

    > g++ -o test main.cpp test_class.cpp ordner/test_class.cpp
    > ./test
    >
    


  • Stimmt, ich sehe nur eine test_class.o Datei. Ich lass das Makefile von qmake generieren. Da muss wohl was nicht stimmen.

    EDIT: Okay, ich habe das Makefile mal eben angepasst, jetzt läufts problemslos. Fragt sich, wie ich das jetzt auf Dauer machen soll. Aber auf jeden Fall: Danke!



  • in Visual Studio ist das auch lustig

    Man macht zwei Klassen z. B. vector3f in Verschiedenen Namespace - die 4 Dateien dafür nennet man jeweils vector3f.h bzw. vector3f.cpp.

    Folgende Ordnerstruktur:

    Ordner1
    +- vector3f.h      // z. B. Foo::vector3f
    +- vector3f.cpp
    Ordner2
    +- vector3f.h      // z. B. Bar::vector3f
    +- vector3f.cpp
    

    nun übersetzt man das Ganze -> Linkerfehler
    Abhilfe schafft man indem man die Dateien z. B. in foo_vector3f.h bzw. bar_vector3f.h umbenennt



  • Dann ist doch der ganze Namespace Wirrwarr umsonst.



  • Ich denke hier handelt es sich um ein Compilerproblem - nicht um ein Sprachproblem - aber was der C++ Standard dazu genau sagt weiß ich nicht

    Abgesehen davon verwende ich hauptsächlich Namespaces nicht um Namenskollisionen zu vermeiden, sondern um meine Software in logische Teile zu gruppieren - ich bilde meistens UML Packages direkt auf Namespaces ab - logische Aufteilung ist z. B. DataManagement, UserInterface, ImageProccessing, Math usw.



  • Genau das hab ich auch vor.



  • Dann ist der ganze Namespace Wirrwarr nicht umsonst. 🙂



  • In der Hinsicht schon, ja :).


Anmelden zum Antworten