Problem mit friend-Dekleration



  • Hallo,

    ich habe eine Klasse innerhalb eines eigenen Namespaces deklariert. Für diese Klasse möchte ich den globalen Ausgabeoperator überladen. Dazu habe ich in der Klassendefinition die Friend-Deklaration hinzugefügt. Leider wird anscheinend diese Deklaration bei mir nich richtig erkannt und es kommt die Fehlermeldung, dass das Attribut "var1" der Klasse "KlasseA" als privat definiert ist und ich daher darauf nicht zugreifen kann.

    Mein Beispiel besteht aus zwei Dateien.
    Die Header-Datei der Klasse "KlasseA.h"

    #include <iostream>
    
    #ifndef KLASSEA_H_
    #define KLASSEA_H_
    
    namespace MyNamespace {
    	class KlasseA{
    		private:
    			int var1;
    
    		public:
    			KlasseA();
    			friend std::ostream & operator<<( std::ostream& strm, MyNamespace::KlasseA & lsystem);
    	};
    }
    
    std::ostream & operator<<( std::ostream& strm, MyNamespace::KlasseA & lsystem);
    
    #endif /* KLASSEA_H_ */
    

    Und der Datei "KlasseA.cpp", die die Funktionen dieser Klasse enthält:

    #include "KlasseA.h"
    
    using namespace MyNamespace;
    
    KlasseA::KlasseA()
    {
    	this->var1 = 10;
    }
    
    std::ostream & operator<<( std::ostream& strm, MyNamespace::KlasseA & lsystem)
    {
    	strm << lsystem.var1 << std::endl;
            return strm;
    }
    

    Als Compiler benutze ich den gcc.

    Zu dem Thema globale Überladung eines Operators habe ich einige Einträge im Web gefunden (z.B. http://stackoverflow.com/questions/3312269/c-friend-function-operator-overloading-istream oder http://www.cplusplus.com/forum/beginner/13164/) Leider bin ich aus den Beiträgen nicht schlau geworden.

    Wenn ich Definition des eigenen Namespaces weglasse, compiliert das Programm.
    Wie jedoch muss ich den Operator definieren, damit es auch mit einem eigenen Namespace klappt?

    Viele Grüße,

    ottixus



  • Wie wär's hiermit?

    friend std::ostream & ::operator<<( std::ostream& strm, MyNamespace::KlasseA & lsystem);
    

    Ist nur geraten.



  • Wenn ich die Friend-Deklaration so abändere, wie du vorgeschlagen hast, bekomme ich folgende Fehlermeldung:

    error: ‘std::ostream& operator<<(std::ostream&, MyNamespace::KlasseA&)’ should have been declared inside ‘::’
    make: *** [src/KlasseA.o] Fehler 1

    Die Fehlermeldung, dass das Attribut private ist, wird aber nicht mehr angezeigt. Ich vermute, weil der Compiler nun erst gar nicht soweit kommt.



  • Das hier kompiliert:

    #include <iostream>
    
    namespace MyNamespace 
    {
    	class KlasseA;	
    }
    
    std::ostream& operator<<(std::ostream& strm, const MyNamespace::KlasseA& lsystem);
    
    namespace MyNamespace 
    {
        class KlasseA
        {
            private:
                int var1;
    
            public:
                KlasseA(int x): var1(x) {}
                friend std::ostream& ::operator<<(std::ostream& strm, const KlasseA& lsystem);
        };
    }
    
    std::ostream& operator<<(std::ostream& strm, const MyNamespace::KlasseA& lsystem)
    {
    	strm << lsystem.var1;
    	return strm;
    }
    
    int main()
    {
    	MyNamespace::KlasseA a(1);
    	std::cout << a << "\n";
    }
    


  • Warum muss dein operator<< global sein?
    Definiere ihn im Namespace, über ADL wird er gefunden.

    http://en.wikipedia.org/wiki/Argument-dependent_name_lookup



  • Der Quellcode von "__cu" kompiliert bei mir auch. Allerdings nur, wenn alles in einer Datei steht. Wenn ich den Code in Header und Cpp-Datei aufteile, erhalte ich den vorhin beschriebene Fehlermeldung, dass der Operator innerhalb des Namensraums von "::" deklariert werden sollte.

    Wenn ich jedoch, wie "einwurf" vorgeschlagen hatte, den Operator innerhalb des Namespaces definiere, kompiliert er einwandfrei.

    Vielen Dank für die Hilfe!

    Der funktionsfähige Code sieht nun so aus:
    Headerdatei:

    #include <iostream>
    
    #ifndef KLASSEA_H_
    #define KLASSEA_H_
    
    namespace MyNamespace {
    	class KlasseA{
    		private:
    			int var1;
    
    		public:
    			KlasseA();
    			friend std::ostream & MyNamespace::operator<<( std::ostream& strm, const KlasseA & lsystem);
    	};
    
    	std::ostream & operator<<( std::ostream& strm, const KlasseA & lsystem);
    
    }
    

    KlasseA.cpp:

    #include "KlasseA.h"
    
    using namespace MyNamespace;
    
    KlasseA::KlasseA()
    {
    	this->var1 = 10;
    }
    
    std::ostream & MyNamespace::operator<<( std::ostream& strm, const MyNamespace::KlasseA & lsystem)
    {
    	strm << lsystem.var1 << std::endl;
    
    	return strm;
    }
    

Log in to reply