Operatoren Überladung::Matrizen::Abarbeitung einer mehrfachen Multiplikation



  • Hallo,

    Machs besser gar nicht so, sondern multipliziere nacheinander. Bei dir wird intern eine temporäre Matrix erzeugt. Desweiteren sollte operator* besser außerhalb der Klasse definiert sein.



  • Gibt es dort denn keine Konvention der man folgen kann ? Der Hintergrund ist der folgende, wenn ich den linken Operanden x in einer Listenform überführe und auf den rechten Operanden y (die Matrix) anwende, hat es sich in meinen Anwendungsfällen als schneller erwiesen. So möchte ich eigentlich mit x*y*z mit entsprechender Überladung erreichen:

    1. x(Matrix) * y(Matrix) * z(Matrix)
    2. x(Liste) * y(Matrix) * z(Matrix)
    3. temp(Matrix) * z(Matrix)
    4. temp(Liste) * z(Matrix)
    5. ergebnis(Matrix)

    Wenn es keine Konvention gibt, kann ich es eh vergessen.

    Desweiteren sollte operator* besser außerhalb der Klasse definiert sein.

    Was meinst Du damit genau ?



  • Ich meine damit, dass du den operator* aus der Klasse raus nehmen solltest (halt global).
    etwa so

    TMatrix operator*(const TMatrix& lhs,  const TMatrix& rhs);
    

    Das in deinem ersten Beitrag ist ja wohl hoffentlich nicht die Deklaration deines Operators.



  • Okay, also eine externe Funktion...

    Braunstein schrieb:

    Das in deinem ersten Beitrag ist ja wohl hoffentlich nicht die Deklaration deines Operators.

    Doch ist es - ich gehe davon aus, daß automatisch Kopien erstellt werden und zwar in der Form:

    1. ergebnis=NULL-Pointer

    1a) x(Matrix) * y(Matrix) * z(Matrix)
    1b) x(Matrix) * y'(Kopie von y) * z(Matrix)

    1. x(Liste) * y'(Kopie von y) * z(Matrix)

    3a) y'(Matrix) * z(Matrix)
    3b) y'(Matrix) * z'(Kopie von z)

    1. y'(Liste) * z'(Kopie von z)

    2. ergebnis=z'(Matrix), y' wird gelöscht

    Diese Abarbeitung innerhalb eines Prozessors würde auch bei einer normalen Multiplikation Sinn machen finde ich, oder nicht ?



  • Winn schrieb:

    Braunstein schrieb:

    Das in deinem ersten Beitrag ist ja wohl hoffentlich nicht die Deklaration deines Operators.

    Doch ist es -

    und dieser operator liefert also nix zurück?



  • Müßte er auch nicht, weil der Wert in die Klasse geschrieben wird... funktionierte sogar in einem Testbeispiel...

    Allerdings verstehe ich nicht, daß die Operatoren-Überladung "nur" zwei Operatoren zu läßt, also x+y. Wenn ich x+y+z mache, bekomme ich einen Compiler Fehler (Gcc 4.01) "main.cpp:46: error: no match for 'operator+' in 'x. count::operator+(((count&)(& y))) + z'". Das Beispiel arbeitet mit Rückgabe, so wie ihr es vorgeschlagen hattet.

    Was fehlt in meiner Klassen-Definition bzw. Deklaration ?

    #include <stdio.h>
    #include <stdlib.h>
    
    class count
    {
    	private:
    		double dValue;
    
    	public:
    		bool showCount() { fprintf(stderr,"Zahl:: %lg\n",dValue); return true; }
    		bool setCount(double val) { dValue=val; return true; }
    		double getValue() { return dValue; }
    
    		count() { dValue=0.; }
    		count(double val) { this->setCount(val); }
    		count(class count *zahl)  { dValue=zahl->getValue(); this->showCount(); }
    		count(class count &zahl)  { dValue=zahl.getValue(); this->showCount(); }
    		void operator=(class count &zahl) { dValue=zahl.getValue(); this->showCount(); }
    
    		class count *operator*(class count &zahl) { class count *foo = new count[1]; foo->setCount(dValue*zahl.getValue()); foo->showCount(); return foo; }
    		class count *operator+(class count &zahl) { class count *foo = new count[1]; foo->setCount(dValue+zahl.getValue()); foo->showCount(); return foo;  }
    		class count *operator-(class count &zahl) { class count *foo = new count[1]; foo->setCount(dValue-zahl.getValue()); foo->showCount(); return foo;  }
    
    		class count *operator*(class count *zahl) { class count *foo = new count[1]; foo->setCount(dValue*zahl->getValue()); foo->showCount(); return foo; }
    		class count *operator+(class count *zahl) { class count *foo = new count[1]; foo->setCount(dValue+zahl->getValue()); foo->showCount(); return foo;  }
    		class count *operator-(class count *zahl) { class count *foo = new count[1]; foo->setCount(dValue-zahl->getValue()); foo->showCount(); return foo;  }
    
    		~count() { dValue=0.; }
    };
    
    int main () 
    {
    	class count x(1);
    	class count y(3);
    	class count z(5);
    	class count *ergebnis = NULL;
    
    	x.showCount();
    	y.showCount();
    	z.showCount();
    
    	ergebnis=x+y;
    	ergebnis->showCount();
    	delete[] ergebnis; ergebnis=NULL;
    
    	ergebnis=x+y+z; // <<== Funktioniert nicht, Compiler Fehler s.o.
    	ergebnis->showCount();
    	delete[] ergebnis; ergebnis=NULL;
    
    	return 0;
    }
    


  • Die Operatoren sollten keine Zeiger zurückgeben, sondern Objekte:

    count operator*(const count& zahl)
    {
      count tmp;
      tmp.value=value*zahl.value;
      return tmp;
    }
    

    So klappt es auch mit der Verkettung der Operatoren.



  • CStoll schrieb:

    Die Operatoren sollten keine Zeiger zurückgeben, sondern Objekte:So klappt es auch mit der Verkettung der Operatoren.

    Das stimmt... aber die Werte-Übergabe bekomme ich irgendwie nicht hin.

    int main () 
    {
    	class count x(1);
    	class count y(3);
    	class count z(5);
    	class count *ergebnis = NULL;
    
    	x.showCount();
    	y.showCount();
    	z.showCount();
    	fprintf(stderr,"\n");
    
    	x+y+z;
    	(x+y+z)*z-y;
    
    	ergebnis=&(x+y);
    	ergebnis->showCount("hat's den wert noch ?");
    
    	return 0;
    }
    

    Meine Ausgabe:

    Zahl ((null)):: 1
    Zahl ((null)):: 3
    Zahl ((null)):: 5

    Zahl (+Operator):: 4
    Zahl (+Operator):: 9
    Zahl (+Operator):: 4
    Zahl (+Operator):: 9
    Zahl (*Operator):: 45
    Zahl (-Operator):: 42
    Zahl (+Operator):: 4
    Zahl (hat's den wert noch ?):: 0

    #include <stdio.h>
    #include <stdlib.h>
    
    class count
    {
    	private:
    		double dValue;
    
    	public:
    		bool showCount(char *comment=NULL) { fprintf(stderr,"Zahl (%s):: %lg\n",comment,dValue); return true; }
    		bool setCount(double val) { dValue=val; return true; }
    		double getValue() { return dValue; }
    
    		count() { dValue=0.; }
    		count(double val) { this->setCount(val); }
    		count(class count &zahl)  { dValue=zahl.getValue(); this->showCount("Konstruktor"); }
    		void operator=(class count &zahl) { dValue=zahl.getValue(); this->showCount("v=Konstruktor"); }
    
    		class count operator+(class count &zahl) 
    		{ 
    			class count foo(0.); 
    			foo.setCount(dValue+zahl.getValue()); 
    			foo.showCount("+Operator"); 
    			return foo;  
    		}
    
    		class count operator-(class count &zahl) 
    		{ 
    			class count foo(0.); 
    			foo.setCount(dValue-zahl.getValue()); 
    			foo.showCount("-Operator"); 
    			return foo;  
    		}
    
    		class count operator*(class count &zahl) 
    		{ 
    			class count foo(0.); 
    			foo.setCount(dValue*zahl.getValue()); 
    			foo.showCount("*Operator"); 
    			return foo;  
    		}
    
    		~count() { dValue=0.; }
    };
    


  • 🙄 Was soll denn das Gegurke (sorry) mit den Zeigern? Du kannst die Objekte ganz normal per Wert übernehmen und weiterreichen:

    int main () 
    {
        count x(1);
        count y(3);
        count z(5);
        count ergebnis;
    
        ergebnis=(x+y)*z;
        ergebnis.showCount("hat's den wert noch ?");
    
        return 0;
    }
    


  • main.cpp:58: error: no match for 'operator=' in 'ergebnis = count::operator-(count&)(((count&)(& y)))'
    Weil mein Compiler die Arbeit verweigert 😉 Die Fehlermeldung ist eigentlich auch ganz logisch, denn die Operatoren Überladung erzeugt ein Objekt dessen Inhalt ich in ein schon vorhandenes Objekt legen möchte...



  • Was für eine Zeile erzeugt denn diesen Fehler? Das sieht zumindest ganz danach aus, daß du deinen operator= vermurkst hast (für Operator-Verkettung sollte der übrigens *this per Referenz zurückgeben).

    PS: Noch ein Schönheitsfehler: In C muß man 'struct irgendwas' immer mit angeben, in C++ kannst du das 'class' weglassen, wenn du den Typ verwenden willst.



  • CStoll schrieb:

    Das sieht zumindest ganz danach aus, daß du deinen operator= vermurkst hast

    In der Tat, es fehlte mir der Adress-Operator "&" 👍 Vielen Dank 🤡

    #include <stdio.h>
    #include <stdlib.h>
    
    class count
    {
    	private:
    		double dValue;
    
    	public:
    		bool showCount(char *comment=NULL) { fprintf(stderr,"Zahl (%s):: %lg\n",comment,dValue); return true; }
    		bool setCount(double val) { dValue=val; return true; }
    		double getValue() { return dValue; }
    
    		count() { dValue=0.; this->showCount("Create"); }
    		count(double val) { this->setCount(val); this->showCount("Init"); }
    		count(class count &zahl)  { dValue=zahl.getValue(); this->showCount("Copy"); }
    
    		class count &operator=(class count &zahl) 
    		{ 
    			if (this==&zahl) return *this;
    
    			this->setCount(zahl.getValue()); 
    			this->showCount("Assign"); 
    			return *this;
    		}
    
    		class count &operator+(class count &zahl)
    		{
    			fprintf(stderr,"+Operator::%lg + %lg =",this->getValue(),zahl.getValue());
    			this->setCount(dValue+zahl.getValue());
    			fprintf(stderr," %lg\n",this->getValue());
    			return *this;
    		}
    
    		class count &operator-(class count &zahl)
    		{
    			fprintf(stderr,"-Operator::%lg - %lg =",this->getValue(),zahl.getValue());
    			this->setCount(dValue-zahl.getValue());
    			fprintf(stderr," %lg\n",this->getValue());
    			return *this;
    		}
    
    		class count &operator*(class count &zahl)
    		{
    			fprintf(stderr,"*Operator::%lg * %lg =",this->getValue(),zahl.getValue());
    			this->setCount(dValue*zahl.getValue());
    			fprintf(stderr," %lg\n",this->getValue());
    			return *this;
    		}
    
    		~count() { dValue=0.; }
    };
    
    int main ()
    {
        class count x(1);
        class count y(3);
        class count z(5);
        class count ergebnis;
    
        ergebnis=(x+y+z)*z-y;
        ergebnis.showCount("hat's den wert noch ?");
    
        return 0;
    }
    

Anmelden zum Antworten