[Gelöst] Probleme beim Überladen von Operatoren



  • 33 C:\Dev-Cpp\main.cpp no match for 'operator<<' in '(&std::cout)->std::basic_ostream<_CharT, _Traits>::operator<< [with _CharT = char, _Traits = std::char_traits<char>](std::endl [with _CharT = char, _Traits = std::char_traits<char>]) << operator+(((const Complex&)((const Complex*)(&my_Complex_3))), ((const Complex&)((const Complex*)(&my_Complex_1))))'



  • Sorry wegen Vorpost.

    OK danke erstmal cooky451. 👍

    Ich habs jetzt so gemacht (Bitte sofort kritisieren, wenn der Code eurer Meinung nach unschön ist)

    #include <cstdlib>
    #include <iostream>
    
    class Complex{
    
    	private:
    
    		double real;
    		double imaginary;
    
    	public:
    
    		friend std::ostream& operator<<(std::ostream&, Complex&);
    		Complex(double rreal, double iimaginary);
    		double get_real() const;
    		double get_imag() const;
    };
    		Complex operator+(const Complex&, const Complex&);
    		Complex operator-(const Complex&, const Complex&);
    
    int main(int argc, char *argv[])
    {
    
    	Complex my_Complex_1(10.0, 11.1);
    	Complex my_Complex_2(23.23, 3.232);
    	Complex my_Complex_3=my_Complex_1+my_Complex_2;
    	Complex my_Complex_4=my_Complex_1-my_Complex_2;
    
    	std::cout<<my_Complex_2<<std::endl;
    	std::cout<<my_Complex_1<<std::endl;
    	std::cout<<std::endl<<my_Complex_3<<std::endl;
    	std::cout<<std::endl<<my_Complex_4<<std::endl;
    
       system("PAUSE");
       return EXIT_SUCCESS;
    }
    
    Complex::Complex(double rreal, double iimaginary)
    	: real(rreal), imaginary(iimaginary){}
    
    std::ostream& operator<<(std::ostream&, Complex& a){
    
    	std::cout<<a.real<<std::endl<<a.imaginary<<std::endl;
    
    }
    
    Complex operator-(const Complex& a, const Complex& b){
    
    	double lokal_imag_1=a.get_imag();
    	double lokal_real_1=a.get_real();
    	double lokal_imag_2=b.get_imag();
    	double lokal_real_2=b.get_real();
    
    	Complex Complex_sum(lokal_real_1-lokal_real_2, lokal_imag_1-lokal_imag_2);
    }
    
    Complex operator+(const Complex& a, const Complex& b){
    
    	double lokal_imag_1=a.get_imag();
    	double lokal_real_1=a.get_real();
    	double lokal_imag_2=b.get_imag();
    	double lokal_real_2=b.get_real();
    
    	Complex Complex_sum((lokal_real_1+lokal_real_2),(lokal_imag_1+lokal_imag_2));
    	return Complex_sum;
    }
    
    double Complex::get_imag() const{
    
    	return imaginary;
    }
    
    double Complex::get_real() const{
    
    	return real;
    }
    

    Die Addition funktioniert. aber... bei der Subtraktion bekomme ich so was raus:
    1.#QNAHN
    3.343456e+235
    Das stimmt natürlich nicht.
    1.Warum kommt da so ein Mist heraus?

    2. Warum kann ich nicht einfach schreiben:
    [cpp]
    std::cout<<my_Complex_1+my_Complex_2<<std::endl;

    da kommen ganz kryptische Fehlermeldungen.. a la:

    33 C:\Dev-Cpp\main.cpp no match for 'operator<<' in '(&std::cout)->std::basic_ostream<_CharT, _Traits>::operator<< [with _CharT = char, _Traits = std::char_traits<char>](std::endl [with _CharT = char, _Traits = std::char_traits<char>]) << operator+(((const Complex&)((const Complex*)(&my_Complex_3))), ((const Complex&)((const Complex*)(&my_Complex_1))))'
    


  • Code dazu wäre gut.
    Edit: ok, mom.

    Das const fehlt da. Sollte std::ostream& operator << (std::ostream&, const Complex&) heißen.



  • Ok danke.

    Das Problem mit der Subtraktion hat sich erledigt.
    Hatte ein return vergessen bei der Funktion.



  • zu 1: da fehlt das return bei der Subtraktion 😉
    zu 2: du mußt noch die Ausgabe für deine Complex-Klasse definieren, d.h. den Stream-Operator <<:

    ostream& operator <<(ostream& os, const Complex& complex)
    {
      return os << '(' << complex.get_real() << '+i' << complex.get_imag() << ')';
    }
    

    Edit: ups, jetzt erst sehe ich daß du den Operator ja implementiert hast (bzw. versuchst hast, da so wie cooky451 schreibt, das const fehlt ;-).
    Jedoch solltest du dort niemals direkt nach cout schreiben, sondern immer in den übergebenen Stream - falls du mal dies in eine Datei ausgeben willst, würdest du dich wundern!!!



  • Könnte man es den nicht einfach auch so machen mit dem +-Operator?

    Complex& operator+( const Complex& a )
    {
        Complex my_Complex_3( 0,0 );
    
        my_Complex_3.real = a.real+ this->a;
        my_Complex_3.imaginary = a.imaginary + this->b;
    
        return my_Complex_3;
    }
    

    Würde das nicht auch gehen?

    MfG



  • Abgesehen davon, dass du eine Referenz auf ein lokales Objekt zurückgibst:

    Das Problem von operator+ als Memberfunktion besteht darin, dass die Argumente asymmetrisch behandelt werden. Der linke Operand muss vom Typ Complex sein, während der rechte auch durch implizite Konvertierung zustande kommen kann.

    Gerade komplexe Zahlen sind ein gutes Beispiel hierfür, da sich ein Konstruktor

    Complex(double real = 0, double imag = 0);
    

    anbietet, welcher eine implizite Konvertierung von double -Werten ermöglicht. Wäre operator+ ein Member, ergäbe sich folgende Problematik:

    Complex c(1, 2);
    double d = 3;
    
    c + d // Funktioniert
    d + c // Fehler: Linker Operand muss Klassentyp haben
    


  • Hallo Blaubär!

    Ich weiß nicht! 😃

    Aber ich habs gestern noch ein bisschen verfeinert, was den Stil angeht und habs so gemacht:

    Complex operator+(const Complex& a, const Complex& b){
    
    	Complex Complex_temp(a.get_real()+b.get_real(), a.get_imag()+b.get_imag());
    
    	return Complex_temp;
    }
    
    Complex operator-(const Complex& a, const Complex& b){
    
    	Complex Complex_temp(a.get_real()-b.get_real(), a.get_imag()-b.get_imag());
    
    	return Complex_temp;
    

    Wobei ich deine Lösung auch interessant finde. Werd ich gleich mal ausprobieren.

    Danke. 🙂



  • Ok, danke. Ich habe aber noch eine kleinen Fehler gemacht. Es muss natürlich this->real und this->imaginary heißten.

    MfG



  • Zagatho_zero87 schrieb:

    Wobei ich deine Lösung auch interessant finde. Werd ich gleich mal ausprobieren.

    Und dann liest du noch mal schnell den Beitrag von Nexus.
    Und deine temp-Variablen sind auch, na ja, zumindest Ansichtssache. Zugegeben, für das Kompilat wird das keinen Unterschied machen, aber Übersichtlicher wird das dadurch jetzt nicht gerade, oder? :p



  • Ja übersichtlicher nicht, das stimmt.
    Was gefällt dir besser:
    Dies

    Complex operator-(const Complex& a, const Complex& b){
    
        Complex Complex_temp(a.get_real()-b.get_real(), a.get_imag()-b.get_imag());
    
        return Complex_temp; 
    }
    

    oder das

    Complex operator-(const Complex& a, const Complex& b){
    
        double lokal_imag_1=a.get_imag();
        double lokal_real_1=a.get_real();
        double lokal_imag_2=b.get_imag();
        double lokal_real_2=b.get_real();
    
        Complex Complex_sum(lokal_real_1-lokal_real_2, lokal_imag_1-lokal_imag_2);
    
        return Complex_sum;
    }
    

    Da die Summenbildung Complex_sum(...) ist in beiden Fällen ca. gleich lang. Aber es fallen die lokalen Variablen weg.



  • Beide doof. Diese beiden Varianten würden für mich infrage kommen: (solche lokalen Variablen werden natürlich eh wegoptimiert, das was rauskommt ist also das Gleiche.)

    Complex operator - (const Complex& lhs, const Complex& rhs)
    {
      return Complex(lhs.real() - rhs.real(), lhs.imag() - rhs.imag());
    }
    
    Complex operator - (const Complex& lhs, const Complex& rhs)
    {
      double real = lhs.real() - rhs.real();
      double imag = lhs.imag() - rhs.imag();
      return Complex(real, imag);
    }
    

    Aber da kommen wir doch langsam in einen Stilbereich der kaum noch sachlich diskutiert werden kann, insofern mach halt was dir Spaß macht. 🤡



  • OK diese beiden gefallen mir auch besser 🙂
    Warum ich oft nacht dem Stil frage ist, weil ich mit dem Buch C von A bis Z gelernt habe (ca. 3-4 Monate) und dann auf C++ umgestiegen bin (C++Primer und Die C++ Programmiersprache) und ich IMHO immer noch den Stil von C von A bis Z mitschleppe. 🙄



  • Sehr hilfreicher Thread, danke.
    Jedoch verstehe ich die Operationsüberladung des <<-Operators nicht.

    ostream& operator <<( std::ostream& os, const Vec& data )
    {
    	return os << data.x1;
    }
    

    Warum muss std::ostream& os als Parameter mit dazu? Ich würde mich über eine Erklärung sehr freuen.

    MfG yihaaa



  • yihaaa schrieb:

    Warum muss std::ostream& os als Parameter mit dazu? Ich würde mich über eine Erklärung sehr freuen.

    Weil da reingeschrieben wird? 😉



  • Ja könnte man den auch std::cout direkt da nehmen und den Parameter weglassen?

    MfG



  • yihaaa schrieb:

    Ja könnte man den auch std::cout direkt da nehmen und den Parameter weglassen?

    Warum denn das? schreib eine Funktion print() ohne Parameter, die macht das auch. Der operator<< ist ja eben dafür da, generisch für alle ostreams zu funktionieren, sei es jetzt cout, ein fstream oder was eigenes von ostream abgeleitetes.



  • yihaaa schrieb:

    Ja könnte man den auch std::cout direkt da nehmen und den Parameter weglassen?

    Der operator << braucht eh zwei Operanden, von daher nicht nur nicht sinnvoll, sondern auch unmöglich. 😉


Anmelden zum Antworten