Überaldung von "="



  • @Krümelkacker: Hier mal nochmal die Variante die du mir vorgeschlagen hast. Ich hoffe, dass das dem entspricht, was du mir beibringen wolltest:

    #ifndef TEST_H
    #define TEST_H
    
    class Vector
    {
    private:
    	double x;
    	double y;
    	double skalar;
    
    public:
    	Vector();
    	Vector(double _x, double _y);
    
    	Vector &operator += (const Vector vec);
    	Vector &operator + (const Vector vec);
    
    	Vector &operator -= (const Vector vec);
    	Vector &operator - (const Vector vec);
    
    	double &operator * (const Vector vec);
    	friend std::ostream &operator << (std::ostream &output, const Vector &v);
    };
    
    #endif TEST_H
    
    #include<iostream>
    #include"test.h"
    
    Vector::Vector() : x(0), y(0)
    {
    
    }
    
    Vector::Vector(double _x, double _y) : x(_x), y(_y)
    {
    
    }
    
    Vector& Vector::operator += (const Vector vec)
    {
    	x = x + vec.x;
    	y = y + vec.y;
    
    	return *this;
    }
    
    Vector& Vector::operator + (const Vector vec)
    {
    	Vector tmp(x, y);
    
    	return tmp += vec;
    }
    
    Vector& Vector::operator -= (const Vector vec)
    {
    	x = x - vec.x;
    	y = y - vec.y;
    
    	return *this;
    }
    
    Vector& Vector::operator - (const Vector vec)
    {
    	Vector tmp(x, y);
    
    	return tmp -= vec;
    }
    
    double& Vector::operator * (const Vector vec)
    {
    	x = x * vec.y;
    	y = y * vec.y;
    	skalar = x + y;
    
    	return skalar;
    }
    
    std::ostream& operator << (std::ostream &output, const Vector &v)
    {
    	output << "(" << v.x << "," << v.y << ")" << std::endl;
    
    	return output;
    }
    

    Danke Nymer, dass du mich nochmal drauf aufmerksam gemacht hast! Jetzt funktioniert übrigens die gesamte Klasse! Danke an euch. Das hat mir sehr weiter geholfen! Über eine Rückmeldung von Krümelkacker würde ich mich sehr freun, ob das dem entspricht, was er mir beibringen wollte 🙂



  • Du kannst übrigens direkt:

    return output << "(" << v.x << "," << v.y << ")" << std::endl;
    

    schreiben anstatt:

    output << "(" << v.x << "," << v.y << ")" << std::endl;
    
        return output;
    

    , was den gleichen Effekt hat.
    Ich persönlich finde das schöner 😉 .



  • vip@r schrieb:

    @Krümelkacker: Hier mal nochmal die Variante die du mir vorgeschlagen hast. Ich hoffe, dass das dem entspricht, was du mir beibringen wolltest:

    Du gibst bei operator+ und co Referenzen auf temporäre Objekte zurück, die dann ungültig werden. Bei operator+ und co fehlt noch ein const am Ende der Deklarationen. Die Parameter würde ich als Referenz-auf-konstant entgegen nehmen. Operator verändert das Objekt auf der linken Seite und gibt eine Referenz auf ein Datenelement der linken Seite zurück*. Das ist eine extrem schlechte Idee für einen binären Operator, der normalerweise seine Operanden nicht verändert und nur einen neuen Wert zurück gibt.

    Nur mal so ein Beispiel:

    Vector& Vector::operator + (const Vector vec)
    {
    	Vector tmp(x, y);
    	return tmp += vec;
    }
    

    hätte lieber

    Vector Vector::operator + (const Vector& vec) const // <- const nicht vergessen!
    { //  ^ keine Referenz!!               ^ Referenz!!
        Vector tmp(x, y);
        tmp += vec;
        return tmp; // <-- so aufgeschrieben erlaubt es noch die NRVO-Optimierung
    }
    

    heißen sollen. Allerdings kannst du es auch so schreiben:

    Vector Vector::operator + (const Vector& vec) const
    {
        return Vector(x+vec.x,y+vec.y);
    }
    

    wobei ich natürlich nicht weiß, was das mit deinem skalar -Member da soll. Der wird ja nicht mal irgendwo initialisiert!

    Prinzipiell würde ich operator+, operator-, operator* aus "Symmetriegründen" auch als freie Funktionen definieren. Was das genau heißt, hatte ich letztens schon angedeutet.

    Du musst übrigens nicht das Rad neu erfinden. Es gibt beispielsweise eine nette Matrix/Vektor-Bibliothek mit diversen netten Funktionen: Eigen.



  • krümelkacker schrieb:

    Prinzipiell würde ich operator+, operator-, operator* aus "Symmetriegründen" auch als freie Funktionen definieren. Was das genau heißt, hatte ich letztens schon angedeutet.

    Das würde ich unbedingt machen und so macht man es afaik auch.
    Wenn du z.B. noch multiplizieren mit einem Skalar hinzufügst, geht das so nicht (V*s) geht (s*V) nicht.

    Du musst übrigens nicht das Rad neu erfinden. Es gibt beispielsweise eine nette Matrix/Vektor-Bibliothek mit diversen netten Funktionen: Eigen.

    Eigen ist toll. Einfach inkludieren und fertig.
    Vielleicht will er aber auch einfach operatoren Überladung üben.



  • Danke Leute, für eure tollen Beispiele und Hilfe!

    Ja, ich will in der Tat die Operatorüberladung üben. Ich werde mir so gut es geht mir eure Tips zu herzen nehmen! Ich hab hier nun übrigens wieder ein Problemchen mit einer Klasse und einer Überladung. Verwendete IDE und Compiler: VS2010.

    Header:

    class Bitvector
    {
    private:
    	unsigned int bits;	//Anzahl der Bits im Bitvektor
    	unsigned char byte;	//chars aus denen sich der Bitvektor zusammensetzt
    	unsigned char* bv;	//pointer auf die aneinandergereihten chars
    
    public:
    	Bitvector();
    	Bitvector(unsigned int bits);
    	~Bitvector();
    
    	friend std::ostream& operator << (std::ostream& output, Bitvector &bv);
    };
    

    Implementierung:

    std::ostream& operator << (std::ostream &output, const Bitvector &bv)
    {
    	bv.bits; //hier gibts den Fehler!
    
    return output;
    }
    

    Compilerfehler:

    Fehler	1	error C2248: "Bitvector::bits": Kein Zugriff auf private Member, dessen Deklaration in der Bitvector-Klasse erfolgte.
    

    Ich brauch in der Überladung Zugriff auf die "bits" der Klasse. Wie mach ich das dann hier? Ich hab eigentlich gedacht, dass ich hier ohne Probleme mein Wissen von gester anwenden kann, aber schon kommt wieder was das mich raushaut... Könnt ihr mir helfen?

    Edit:
    Wenn ich den Zugriffsspezifizierer private auf public ändere, bekomme ich hier Zugriff auf bits. Warum kann ich bei dieser Ausgabeoperator-Überladung nicht, wie in "normalen" Methoden üblich, auf private-Variablen zugreifen? Wie gehe ich dann hier vor? Muss ich eine Methode schreiben, die mir den Wert private-Var. liefert? Oder gibt es eine andere Möglichkeit?



  • friend gewährt einer Methode Zugriff auf private Daten einer Klasse (solltest du wissen). Deine beiden Methoden haben nicht die gleiche Signatur, weshalb die Implementation nicht als die friend Methode erkannt wird. ( const zuwenig)

    Übrigens wie mein Compiler richtig meckert, musst du so unbedingt den Copy-Konstruktor und den operator= überladen. Am besten gar keine Pointer verwernden.



  • Wenn ich deine Antwort richtig verstehe, muss ich also in der Implementierung das friend-Schlüsselwort auch noch schreiben, oder? Leider finde ich hierzu in meinem Buch/Unterlagen leider kein Beispiel wo das gezeigt wird an welche Stelle das friend platziert werden muss...

    Edit: "friend" darf außerhalb einer Klasse nicht verwendet werden, sagt mein Compiler. Wo ist dann der Fehler?

    Das friend den Zugriff auf private Vars/Methoden regelt weiß ich natürlich, deswegen hab ich es ja in der h-Datei auch hingeschrieben 🙂



  • [cpp]class Bitvector
    {
    ...
    friend std::ostream& operator << (std::ostream& output, Bitvector &bv);
    }; [/cpp]

    std::ostream& operator << (std::ostream &output, const Bitvector &bv)
    {
        bv.bits; //hier gibts den Fehler!
    
    return output;
    }
    

    Das meinte ich. (Steht da doch auch(Hmm.. vielleicht auch etwas mehrdeutig))



  • Ich bin blind. Leider. Aber dennoch Danke 🙂

    Nun hab ich die Überladung um das hier erweitert:

    std::ostream& operator << (std::ostream &output, const Bitvector &bv)
    {
    	for(unsigned int i=0; i<=bv.bits; i++)
    	{
    		if(i == 0)
    		{
    			output << bv.getBit(i);  //Fehler
    		}
    		else if((i%4) == 0)
    		{
    			output << " " << bv.getBit(i);  //Fehler
    		}
    		else if(i > 0)
    		{
    			output << bv.getBit(i);  //Fehler
    		}
    	}
    
    return output;
    }
    

    Probleme macht nun die getBit()-Methode. Der Compiler sagt: "Fehler 1 error C2662: 'Bitvector::getBit': this-Zeiger kann nicht von 'const Bitvector' in 'Bitvector &' konvertiert werden"

    Die getBit()-Methode gibt einen einzelnen char zurück. Wie greife ich korrekt auf Methoden aus Überladungen zu? Es liegt am const, nicht wahr? Muss ich nun die getBit() als const deklarieren?



  • vip@r schrieb:

    Die getBit()-Methode gibt einen einzelnen char zurück. Wie greife ich korrekt auf Methoden aus Überladungen zu? Es liegt am const, nicht wahr? Muss ich nun die getBit() als const deklarieren?

    Ja.

    Sag mal: Wie lernst du eigentlich C++? Es sieht nämlich nicht so aus, als hättest du ein schlaues C++ Buch vor dir liegen. Man würde dann erwarten, dass du dann schon viel weiter wärst.



  • Sag mal, liest du eigentlich das, was der Compiler als Fehlermeldung ausgibt, das, was wir dir sagen und das was in deinem Buch steht?


Anmelden zum Antworten