Problem beim Überladen von Operatoren



  • Dieses Problem wurmt mich schon seit einer ganzen Weile:

    Minimalbeispiel:

    #include<vector>
    using std::vector;
    
    class zahl {
    	private:
    		double inhalt;
    	public:
    		zahl(double& eingabe) : inhalt(eingabe) {
    		};
    		zahl& operator=(zahl& operand_re) {
    			this->inhalt = operand_re.inhalt;
    			return (*this);
    		};
    		zahl operator*(double& faktor) {
    			zahl ergebnis(*this);
    			ergebnis.inhalt *= faktor;
    			return ergebnis;
    		};
    };
    
    class vielezahlen {
    	private:
    		vector<zahl> folge;
    	public:
    		vielezahlen() : folge(vector<zahl>()) {
    		};
    
    		vielezahlen operator*(double& faktor) {
    			vielezahlen ergebnis(*this);
    			for(vector<zahl>::iterator i = ergebnis.folge.begin(); //
    				i != ergebnis.folge.end(); ++i)
    				*i = *i * faktor; //<-Fehler
    			return ergebnis;
    		};
    };
    
    int main(int argc, char* argv[]) {
    	return 0;
    }
    

    Das Problem ist also, dass ich eine Klasse1 habe, für die eine Multiplikation mit double-Werten definiert ist. Außerdem habe ich zweite Klasse die einen std::vector von Elementen der Klasse1 enthält. Für die zweite Klasse möchte ich eben einfach ebenfalls eine Multiplikation mit double-Werten derart definieren, dass die Multiplikation auf alle Elemente im vector angewended wird.

    Der Compiler mekert rum, dass er den richtigen Funktionsaufruf

    no match für »operator=« in »i.__gnu_cxx::__normal_iterator<_Iterator, _Container>::operator* [with _Iterator = zahl*, _Container [...]

    Anmerkung: Kandidaten sind: zahl& zahl::operator=(zahl&)

    nicht finden kann. Ich bin der Meinung ich hätte ein ähnliches Problem vor Jahren schon einmal lösen können, indem ich anstatt die Operatoren zu überladen einfach gewöhnliche Element-Funktionen für die Aufgaben geschrieben hätte, aber da C++ nun einmal das Überladen der Operatoren anbietet, würde ich schon gern damit arbeiten wollen.

    Gruß, der Kotfluegel

    (Nur so nebenbei: Benötigen tu ich das eben, weil ich ein Mehrkörper-Anfangswertproblem implementieren will, welches mit einem expliziten Runge-Kutta-Verfahren integriert werden soll. Dort habe ich statt der Klasse "zahl" eine 3er-Vektoren-Klasse und Geschwindigkeiten und Orte vieler Teilchen werden mit Hilfe der std-Container zu einer Phasenraumklasse zusammengefasst, deren Objekte eben nach Butcher-Diagrammen mit Zahlen durchmultiplizierbar sein müssen. Zur Zeit hab ich schon alle für mich interessanten RKVs implementiert, es müssen nur noch die benötigten Operatoren funktionieren.)


  • Mod

    const-Korrektness beachten! Gerade bei Referenzen wichtig. Denn in der Fehlerzeile steht rechts ein temporärer Wert (das Ergebnis der Rechnung). Dein Zuweisungsoperator nimmt für die rechte Seite aber eine normale Referenz an und deutet dem Compiler damit an, dass dieser Wert eventuell verändert werden kann. Das ist natürlich nicht möglich, daher der Fehler.

    Dein Programm enthält auch viele unnötige Semikolons und Referenzübergabe von double macht auch nicht viel Sinn, wenn du nichts verändern willst. Ich habe das mal kurz überarbeitet, und dabei die const-Korrektness auch voll durchgezogen:

    #include<vector>
    using std::vector;
    
    class zahl {
    private:
      double inhalt;
    public:
      zahl(double eingabe) : inhalt(eingabe) {}
      zahl& operator=(const zahl& operand_re) 
      {
        this->inhalt = operand_re.inhalt;
        return (*this);
      }
      zahl operator*(double faktor) const
      {
        zahl ergebnis(*this);
        ergebnis.inhalt *= faktor;
        return ergebnis;
      }
    };
    
    class vielezahlen {
    private:
      vector<zahl> folge;
    public:
     /* vielezahlen() : folge(vector<zahl>()) {} */ // Häh, was soll das denn?
    
      vielezahlen operator*(double faktor) const
      {
        vielezahlen ergebnis(*this);
        for(vector<zahl>::iterator i = ergebnis.folge.begin(); i != ergebnis.folge.end(); ++i)
          *i = *i * faktor; 
        return ergebnis;
      }
    };
    

    Üblicherweise überlädt man den Operator* jedoch anders, schau mal hier:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-232010.html
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-240706.html
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-242944.html



  • Ahh, vielen dank für die erleuchtenden Zeilen, sehr hilfreich. 😃


Anmelden zum Antworten