Operandenproblem



  • Danke erstmals.

    Meinst du es so:

    bool operator==(double, complex);
    bool operator!=(double, complex);
    
    bool complex::operator==(complex rightop){
    	return (r==rightop.r && i == rightop.i);
    }
    
    bool complex::operator!=(complex rightop) {
    	return (r!=rightop.r && i!=rightop.i);
    }
    


  • Bei deinem aktuellen Code reicht es sogar schon wenn du die Operatoren einfach als freistehende Funktionen definierst. Du musst nichtmal die verschiedenen Kombinationen complex/complex, double/complex, complex/double hinschreiben, da momentan ein double implizit zu deiner complex Klasse konvertiert werden kann (siehe explicit Keyword). Oft wid ein fehlendes explicit Keyword als Fehler angemerkt, da es zu unerwarteten Konvertierungen führen kann. Für eine complex Klasse mag es allerdings OK sein.



  • Pokerface schrieb:

    Danke erstmals.

    Meinst du es so:

    bool operator==(double, complex);
    bool operator!=(double, complex);
    
    bool complex::operator==(complex rightop){
    	return (r==rightop.r && i == rightop.i);
    }
    
    bool complex::operator!=(complex rightop) {
    	return (r!=rightop.r && i!=rightop.i);
    }
    

    Mit diesen zwei Änderungen kommen folgende Fehler:

    /tmp/cckDrML6.o: In Funktion `main':
    complex1.C:(.text+0x1ea): Nicht definierter Verweis auf `operator==(double, complex)'
    complex1.C:(.text+0x27d): Nicht definierter Verweis auf `operator!=(double, complex)'
    collect2: error: ld returned 1 exit status
    


  • Nein, sondern eben als freie Funktion (d.h. außerhalb der Klasse) mit 2 Parametern, s.a. Überladung von Operatoren in C++ (Teil 1) ("3.8 operator==, !=").



  • Soll es so aussehen?

    bool operator==(complex const&,complex const&);
    bool operator!=(complex const&,complex const&);
    

    Sorry, bin aber noch ein Grünschnabel was die objektorientierte Programmierung angeht.



  • Ja, aber außerhalb von class complex das ist wichtig. (wo du es stehen hast kann man jetzt nur erraten).



  • Danke und wie soll ich nun die beiden externen Methoden definieren bzw implementieren?



  • Wie jede andere freie Funktion auch:

    bool operator==(complex const& lh, complex const& rh)
    {
      return ...;
    }
    


  • Folgenden Fehler bekomm ich jetzt: "Speicherzugriffsfehler (Speicherabzug geschrieben)"



  • Das heißt es compiliert jetzt immerhin schon mal? Zeig mal den Code den du jetzt benutzt.



  • #include <iostream>
    #include "complex.h"
    
    using namespace std;
    
    int main() {
      complex c1(2),c2(3,-4);
      double d1=2, d2(3);
      c2.print(); cout << " ist " << (c2==d2 ? "" : "nicht ") << "gleich ";
      cout << d2 << endl;
      c1.print(); cout << " ist " << (c1!=d1 ? "nicht " : "") << "gleich ";
      cout << d1 << endl;
      cout << d1 << " ist " << (d1==c1 ? "" : "nicht ") << "gleich ";
      c1.print(); cout << endl;
      cout << d2 << " ist " << (d2!=c2 ? "nicht " : "") << "gleich ";
      c2.print(); cout << endl;
      cout << "Die konjugiert komplexe Zahl zu "; c2.conj().print();
      cout << " ist "; c2.print(); cout << endl;
      return 0;
    }
    
    #include<iostream>
    using namespace std;
    
    class complex {
    	double r, i;
    
    	public:
    		complex();
    		complex(double a);
    		complex(double a, double b);
    
    		void print();
    		complex conj();
    
    };
                   bool operator==(complex const& lh,complex const& rh);
                   bool operator!=(complex const& lh,complex const& rh);
    
    #include<iostream>
    #include "complex.h"
    
    using namespace std;
    
    complex::complex() {
    	r=0;
    	i=0;
    }
    
    complex::complex (double a) {
    	r=a;
    	i=0;
    }
    
    complex::complex (double a, double b) {
    	r=a;
    	i=b;
    }
    
    void complex::print() {
    	cout << r;
    	if (i > 0) {
    		cout << "+" << i << "i";
    	}
    	if (i < 0) {
    		cout << i << "i";
    	}
    }
    
    complex complex::conj() {
            return complex(r, -i);
    }
    
    bool operator==(complex const& lh, complex const& rh){
          return (lh==rh);
    
    }
    
    bool operator!=(complex const& lh,complex const& rh) {
          return ! (lh==rh);
    
    }
    


  • Hier hast du mal ne klasse Endlosschleife:

    bool operator==(complex const& lh, complex const& rh){
          return (lh==rh);
    }
    

    Du kannst den operator== nicht Implementieren indem dieser sich selbst aufruft. Du musst schon deinen Code von vorher nehmen der dann Real- und Imaginärteil vergleicht.



  • Ok, danke und wie kann ich nun auf den realen und imaginären Teil zugreifen?



  • Achso der private bei dir. Da gibts 3 Möglichkeiten die mir einfallen:

    1. Du machst die Member public. Eigentlich nicht so schön aber bei komplexen Zahlen kann man dadurch das die Member public sind nichts kaputt machen.
    2. Du erststellst Funktionen um den Real- und Imaginärteil auszulesen. Die sollte man so oder so haben, sonst ist deine Klasse wenig praktisch.
    3. Du befreundest (siehe friend Keyword) die operator== Funktion (etwas unschöne Lösung)



  • Ich habs mal mit der public-Version probiert - hat funktioniert. Danke.
    Da wir aber die Instanzvariablen private haben müssen, muss ich eine andere Variante auswählen.



  • Die friend-Version ist eigentlich gar nicht mal so unschön, schließlich gehört die Funktion ja direkt zur Klasse dazu.



  • Hab es so gelöst, passt das so?:

    #include <iostream>
    #include "complex.h"
    
    using namespace std;
    
    int main() {
      complex c1(2),c2(3,-4);
      double d1=2, d2(3);
      c2.print(); cout << " ist " << (c2==d2 ? "" : "nicht ") << "gleich ";
      cout << d2 << endl;
      c1.print(); cout << " ist " << (c1!=d1 ? "nicht " : "") << "gleich ";
      cout << d1 << endl;
      cout << d1 << " ist " << (d1==c1 ? "" : "nicht ") << "gleich ";
      c1.print(); cout << endl;
      cout << d2 << " ist " << (d2!=c2 ? "nicht " : "") << "gleich ";
      c2.print(); cout << endl;
      cout << "Die konjugiert komplexe Zahl zu "; c2.conj().print();
      cout << " ist "; c2.print(); cout << endl;
      return 0;
    }
    
    #include<iostream>
    #include "complex.h"
    
    using namespace std;
    
    complex::complex() {
    	r=0;
    	i=0;
    }
    
    complex::complex (double a) {
    	r=a;
    	i=0;
    }
    
    complex::complex (double a, double b) {
    	r=a;
    	i=b;
    }
    
    void complex::print() {
    	cout << r;
    	if (i > 0) {
    		cout << "+" << i << "i";
    	}
    	if (i < 0) {
    		cout << i << "i";
    	}
    }
    
    complex complex::conj() {
            return complex(r, -i);
    }
    
    bool operator==(complex const& lh, complex const& rh){
         return (lh.r==rh.r && lh.i == rh.i);
    }
    
    bool operator!=(complex const& lh,complex const& rh) {
         return !(lh.r==rh.r && lh.i == rh.i);
    }
    
    #include<iostream>
    using namespace std;
    
    class complex {
    double r, i;
    
    	public:
    		complex();
    		complex(double a);
    		complex(double a, double b);
    
    		void print();
    		complex conj();
    
                    friend bool operator==(complex const& lh,complex const& rh);
                    friend bool operator!=(complex const& lh,complex const& rh);
    
    };
    
    bool operator==(complex const& lh,complex const& rh);
    bool operator!=(complex const& lh,complex const& rh);
    


  • Ja. Allerdings wäre es wie schon gesagt praktisch trotzdem Funktionen zu haben mit der man den Real- und Imaginär auslesen kann.

    PS: Den operator!= hättest du gar nicht ändern brauchen. Wenn du diesen implementierst indem du den operator== benutzt ist das schon OK.



  • Vielen, vielen Dank 👍



  • SO, eine Frage hätte ich noch 🙂
    Wie wichtig sind die const-Bezeichnungen?
    Ist es ein Problem wenn ich sie einfach weglasse?


Anmelden zum Antworten