falscher operator aufruf


  • Mod

    CStoll schrieb:

    So, wie ich das verstehe, hat der Compiler zwei Möglichkeiten, den Ausdruck "T2 var3 = var1 - var2;" zu deuten:

    1. Verwendung deines op- (vorher Upcast von var1 und var2 in einen T<float,3>&) und des Ctor's 'T2(const T<..>&)'
    2. Verwendung des eingebauten op- für Zeiger (vorher Umwandlung mit deinem operator t*) und des Ctor's 'T2(float,float,float);'

    Und so ist es eigentlich nicht. Welcher operator- benutzt wird, hängt ausschließlich von den Parametern ab, nicht davon, ob wir mit dem Funktionsergebnis weiterkommen. Ob also ein passender Konstruktor in T2 existiert, ist dafür völlig irrelevant. Um den eingebauten operator aufrufen zu können, sind hier für beide Parameter selbstdefinierte Konvertierungssequenzen notwendig, während es für den überladenen Operator genügt, je eine derived-to-base-Konvertierung vorzunehmen. Unser Operator ist keine Templatefunktion, also wird diese Konvertierung auch nicht unterdrückt. Dann kann das Ganze nur noch scheitern, wenn diese derived-to-base-Konvertierung wegen Zugriffsbeschränkung oder Mehrdeutigkeit nicht möglich ist - beides offenbar auch nicht der Fall. Ich glaube daher immer noch, dass der Fehler durch die Vereinfachung des Originals verschwunden ist. wie sieht es denn mit

    var1.operator-(var2);
    

    im Original aus?



  • also ich könnte anbieten beide klassen komplett hier drin zu posten, dann wirds aber sehr unübersichtlich, weil viele codezeilen.


  • Mod

    FreakyBKA schrieb:

    also ich könnte anbieten beide klassen komplett hier drin zu posten, dann wirds aber sehr unübersichtlich, weil viele codezeilen.

    Im Zweifel ist das die sicher Variante.



  • ursprünglich die Klasse T

    template <class t, unsigned int n, unsigned int m>
    class cmatrix
    {
    	private:
    
    		t _elements[n * m];
    
    	public:
    
    		cmatrix();
    		cmatrix(const cmatrix<t, n, m>& src);
    
    		void copy(const cmatrix<t, n, m>& src);
    		void load_identity();
    		void load_null();
    		void load_natural();
    		void load_random();
    
    		void set_element(unsigned int i, unsigned int j, const t& e);
    		const t& get_element(unsigned int i, unsigned int j = 0) const;
    
    		void set_col(unsigned int j, const cmatrix<t, n, 1>& col);
    		void set_row(unsigned int i, const cmatrix<t, 1, m>& row);
    		cmatrix<t, n, 1> get_col(unsigned int j) const;
    		cmatrix<t, 1, m> get_row(unsigned int i) const;
    
    		void swap_row(unsigned int i1, unsigned int i2);
    		void swap_col(unsigned int j1, unsigned int j2);
    
    		cmatrix<t, m, n> transpose() const;
    		cmatrix<t, m, n> pseudo_inverse() const;
    
    		void print() const;
    
    //Operatoren
    		void operator = (const cmatrix<t, n, m>& src);
    		cmatrix<t, n, m>& operator ++ ();
    		cmatrix<t, n, m>& operator -- ();
    		t& operator () (unsigned int i, unsigned int j = 0);
    		const t& operator () (unsigned int i, unsigned int j = 0) const;
    		cmatrix<t, n, m> operator () (const cmatrix<unsigned int, n, 1>& p) const;
    		operator const t* () const;
    
    //Vergleichsoperationen
    		bool operator == (const cmatrix<t, n, m>& r) const;
    		bool operator != (const cmatrix<t, n, m>& r) const;
    
    //Negation
    		cmatrix<t, n, m> operator - ();
    
    //Matrix-Matrix-Operationen
    		cmatrix<t, n, m>& operator += (const cmatrix<t, n, m>& r);
    		cmatrix<t, n, m>& operator -= (const cmatrix<t, n, m>& r);
    		cmatrix<t, n, m>& operator *= (const cmatrix<t, m, m>& r);
    		cmatrix<t, n, m> operator + (const cmatrix<t, n, m>& r) const;
    		cmatrix<t, n, m> operator - (const cmatrix<t, n, m>& r) const;
    
    //Matrix-Skalar-Operationen
    		cmatrix<t, n, m>& operator *= (const t& r);
    		cmatrix<t, n, m>& operator /= (const t& r);
    
    		cmatrix<t, n, m> operator * (const t& r) const;
    		cmatrix<t, n, m> operator / (const t& r) const;
    };
    
    //Ausgabeoperation
    template <class t, unsigned int n, unsigned int m>
    ostream& operator << (ostream& os, const cmatrix<t, n, m>& src);
    
    //Matrix-Matrix-Operationen
    template <class t, unsigned int n, unsigned int m, unsigned int p>
    cmatrix<t, n, p> operator * (const cmatrix<t, n, m>& l, const cmatrix<t, m, p>& r);
    
    //Matrix-Skalar-Operationen
    template <class t, unsigned int n, unsigned int m>
    cmatrix<t, n, m> operator * (const t& l, const cmatrix<t, n, m>& r);
    
    //Skalarprodukt
    template <class t, unsigned int n>
    t operator * (const cmatrix<t, n, 1>& l, const cmatrix<t, n, 1>& r);
    

    ursprünglich die Klasse T2

    class cvertex : virtual public cmatrix<float, 4, 1>
    {
    	public:
    
    		cvertex(float x = 0, float y = 0, float z = 0, float v = 0);
    		cvertex(const cmatrix<float, 4, 1>& src);
    		cvertex(const cvertex& src);
    
    		void set(float x = 0, float y = 0, float z = 0, float v = 0);
    		void set_point();
    		void set_vector();
    		void set_affine();
    		void set_positive();
    
    		float x() const;
    		float y() const;
    		float z() const;
    		float abs2() const;
    		float abs() const;
    		void normalize();
    
    		void draw(float red = 1, float green = 1, float blue = 1, float alpha = 1) const;
    		void set_dot() const;
    
    		void print() const;
    
    		void operator = (const cmatrix<float, 4, 1>& src);
    		void operator = (const cvertex& src);
    		cvertex operator - () const;
    		cvertex& operator ^= (const cvertex& r);
    };
    
    ostream& operator << (ostream& os, const cvertex& src);
    cvertex operator ^ (const cvertex& l, const cvertex& r);
    
    float volume(const cvertex& a, const cvertex& b, const cvertex& c);
    float abs(const cvertex& vertex);
    float abs2(const cvertex& vertex);
    

    bitte nicht schlagen 😃


  • Mod

    wußte doch, dass du was unterschlagen hast 😉

    cvertex operator - () const;
    

    Stichwort Verdeckung.



  • aber das ist doch nur ein negations-operator und kein subtraktions-operator, der eine hat 2 und der andere nur einen parameter.


  • Mod

    FreakyBKA schrieb:

    aber das ist doch nur ein negations-operator und kein subtraktions-operator, der eine hat 2 und der andere nur einen parameter.

    Ob unärer oder binärer Operator ist eine Frage der Grammatik und hat keinen Einfluß auf das Namelookup. Der Name beider Funktionen ist jeweils operator- und nur danach wird erst einmal geschaut. Die Frage nach der passenden Überladung ist erst der zweite Schritt - wir müssen ja erst einmal eine Menage an Kandidaten haben, bevor wir eine Überladung auflösen können. Abhilfe könnte z.B. eine using-Deklaration bringen:

    using cmatrix<float, 4, 1>::operator-;
    

    oder du machst gleich eine freie Funktion daraus.



  • aber der operator passt doch überhaupt nicht auf die anweisung

    cvertex var3 = var1 - var2;
    

    ich meine mit diesem negations-operator kann er doch nichts anfangen


  • Mod

    FreakyBKA schrieb:

    aber der operator passt doch überhaupt nicht auf die anweisung

    cvertex var3 = var1 - var2;
    

    ich meine mit diesem negations-operator kann er doch nichts anfangen

    richtig, deshalb nimmt er ja auch den eingebauten Operator für Zeiger. Das Problem ist, dass er die eigentlich gewollte Überladung nicht findet, weil der Namensraum der Basisklasse gar nicht erst durchsucht wird.



  • den negations-operator von cmatrix<float, 4, 1> soll er ja eben nicht verwenden, weil der komplett negiert, was ich bei cvertex nicht haben will, der soll nämlich nur die erste 3 werte negieren und den 4. unberührt lassen



  • und was genau muss jetzt ändern damit das so funktioniert wie ich das möchte?



  • Eigentlich wird nur der unäre Operator der Basisklasse verdeckt. Beim binären Operator handelt es sich tatsächlich um eine Überladung, da beide Funktionen sich in ihrer Signatur unterscheiden.


  • Mod

    struct A
    {
      void f(int,int);
    };
    struct B : A
    {
      void f(int);
    };
    void foo()
    {
      B b;
      b.f(1,1);
    }
    

    gleiche Konstellation. Natürlich kann die Überladung in B nicht genutzt werden, weil die Parameteranzahl nicht stimmt. Trotzdem wird die Basisklasse nicht durchsucht, denn die bloße Suche nach dem Namen f ist bereits erfolgreich gewesen. Nur sind eben alle gefunden Überladungen in B unbrauchbar und der Compiler quittiert es mit einem Fehler. In deinem Falle gibt es dann aber noch die Alternative des eingebauten Operators, deswegen bekommst du nichts zu sehen.



  • Tja, wieder was gelernt.

    Mal ne andere Frage: Wieso deklarierst Du du Deine Vererbung da als virtual? Das macht doch nur bei Mehrfachvererbung Sinn, oder?



  • na ich wusste nicht genau ob sich das überträgt, wenn ich später vllt mal ne klasse habe die von cmatrix und cvertex erbt. also

    class T1
    {};
    
    class T2 : public T1
    {};
    
    class T3 : public T2, public T1
    {};
    

    da wusste ich jetzt nicht ob es ausreicht bei T3 einfach virtual davor zu schreiben ober ob das bei T2 schon hin muss, und da hab ich es sicherheitshalber schon bei T2 gemacht.
    mal abgesehen davon weiß ich auch gar nicht genau welche klasse da priorität hat, da ja doch einige operatoren/methoden 'gleich' sind.



  • jetzt würde ich aber trotzdem noch gern wissen, wie ich mein ursprüngliches problem lösen kann ohne meinen halber code ändern zu müssen :D.

    PS: zum thema mal wieder was gelernt, kann ich nur sagen das ich öfters für solche sachen sorge und jedesmal lerne ich durch die angeregten diskussionen und engagierten helfer sehr viel dazu 😉


  • Mod

    FreakyBKA schrieb:

    jetzt würde ich aber trotzdem noch gern wissen, wie ich mein ursprüngliches problem lösen kann ohne meinen halber code ändern zu müssen :D.

    using-Deklaration in cvertex s.o.



  • wo muss das hin? in dem zusammenhand hab ich das using noch nicht verwendet ...


  • Mod

    einfach in die Klassendefinition von cvertex einfügen. Ist eine Deklaration wie jede andere.



  • wunderbar funktioniert.
    also vielen dank an die, die sich so tatkräftig beteiligt haben. immer wieder eine freude mit so fachkundigen leuten zusammenzuarbeiten 👍


Anmelden zum Antworten