falscher operator aufruf
-
Ja, da hast Du allerdings recht @camper.
Das gesamte Interface der Klasse wäre allerdings schon hilfreich.
-
Das war Mist, bitte löschen.
-
das was ich da geschrieben habe ist eine vereinfachte und reduzierte variante der tatsächlichen klassen (über 100 zeilen). deswegen sind auch die namen nur als T bzw T2 gegeben um es auf das wesentliche zu reduzieren.
für T gibts folgende Konstruktoren und interne Operatoren:
T(); T(const T<t, n>& src); void operator = (const T<t, n>& src); operator const t* () const; T<t,n> operator - (const T<t,n>& r);für T2 gibts folgende Konstruktoren und interne Operatoren:
T2(float x = 0, float y = 0, float z = 0); T2(const T<float, 3>& src); void operator = (const T<float, 3>& src);und T2 ist wie gesagt von T abgeleitet also:
class T2 : virtual public T {//... };und ja er ruft bei der Anweisung zweimal den Cast-Operator auf und scheint die dann voneinander abzuziehen, warum auch immer das geht.
-
jetzt war ich selbst ein wenig verwirrt. Subtrahieren kann man zwei Zeiger schon: p1-p2== distance(p2,p1) ... naja, Konvertierungsoperatoren sind sowieso ziemlich böse, wenn man nicht sehr aufpasst.
Ich behaupte allerdings, das hier noch eine weiter Deklaration stört. Jedenfalls ruft mein Compiler hier nicht den Konvertierungsoperator auf.
#include <iostream> using namespace std; template <class t, unsigned int n> class T { private: t* data[n]; public: T() { cout << "T::T()" << endl; } T(const T<t, n>& src) { cout << "T::T(const T&)" << endl; } void operator = (const T<t, n>& src) { cout << "void T::operator=(const T&)" << endl; } operator const t* () const { cout << "T::operator const t*()" << endl; return data; } T<t,n> operator - (const T<t,n>& r) { cout << "T T::operator-(const T&)" << endl; return *this; } }; class T2: virtual public T<float, 3> { public: T2(float x = 0, float y = 0, float z = 0) { cout << "T2::T2(float=0,float=0,float=0)" << endl; } T2(const T<float, 3>& src) { cout << "T2::T2(const T<float,3>&)" << endl; } void operator = (const T<float, 3>& src) { cout << "coid T2::operator=(const T<float,3>&)" << endl; } }; int main() { T2 var1, var2; T2 var3 = var1 - var2; }
-
Was mich da wundert, ist, daß es keinen passenden Konstruktor gibt. Ein entsprechender Konstruktor müsste auch einen Pointer übernehmen und keine Objektreferenz.
Probier als Workarround doch mal, den Cast selbst als explicit zu deklarieren.
-
Der folgende Konstruktor wird benutzt:
T2(float x = 0, float y = 0, float z = 0);Die Differenz der beiden Zeiger liefert ein Int, und der passt zu dem oben stehenden Konstruktor. Irgendwie ziemlich böse.
Wieso dabei aber das ganze implzite Geknispel dem direkt passenden Wert vom Subtraktions-Operator vorgezogen wird, ist mir schleierhaft.
Setzte in dem obenstehenden Konstruktor mal eine Ausgabe ein. Ich schätze mal der wird aufgerufen.
-
ja das meinte ich ja, mein fehler, der konvertiert erst var1 und var2 in t* und ruft dann den constructor mit x,y,z auf.
wie definiere ich denn das zeugs explizit? und was genau bewirkt das?
-
explicit als Schlüsselwort mit rein (Google hilft
)
Mir ist nur Schleierhaft, wieso das Casten und implizite Umwandeln von int nach float dem direkt passenden operator- und dem Copy-Konstruktor vorgezogen wird. Bei mir ist das nicht so.
-
Tachyon schrieb:
explicit als Schlüsselwort mit rein (Google hilft
)
Mir ist nur Schleierhaft, wieso das Casten und implizite Umwandeln von int nach float dem direkt passenden operator- und dem Copy-Konstruktor vorgezogen wird. Bei mir ist das nicht so.es ist aucht nicht so. Wenn das ein vereinfachtes Beispiel ist, gehe ich davon aus, dass sich beim Vereinfachen ein Fehler eingeschlichen hat.
-
beim vereinfachen ist kein fehler passiert, habe es gerade nochmal durchgeschaut.
also ich hab mir jetz mal das mit explicit angeschaut, allerdings hab ich jetz ein anderes problem. nämlich:T2 var3 = var2 - var1;das funktioniert jetzt nicht mehr, warum auch nicht?
weil es gibt ja den copy-constructor über die klasse T, der das eigentlich abwickeln sollte.
-
FreakyBKA schrieb:
beim vereinfachen ist kein fehler passiert, habe es gerade nochmal durchgeschaut.
Dann sollte es sich aber nicht anders verhalten. Welchen Compiler setzt du denn ein?
also ich hab mir jetz mal das mit explicit angeschaut, allerdings hab ich jetz ein anderes problem. nämlich:
T2 var3 = var2 - var1;das funktioniert jetzt nicht mehr, warum auch nicht?
weil es gibt ja den copy-constructor über die klasse T, der das eigentlich abwickeln sollte.Was heißt funktioniert nicht? Fehlermeldung des Compilers? wenn ja, welche? Im Übrigen sind hier zwei Konstruktoren von T2 beteiligt und die von T eigentlich nur als Teil dieser anderen Konstruktoren.
-
als compiler hab ich den VC++ Express 2005.
error C2440: 'initializing' : cannot convert from '__w64 int' to 'T2' Constructor for class 'T2' is declared 'explicit'weil ich jetzt den einen constructor explizit gemacht habe
explicit T(float x = 0, float y = 0, float z = 0, float v = 0);also er konvertiert var1 und var2 immernoch in (t*)
also gedacht war das ja so, das ich die operatoren in T definiere und in T2 mitverwenden kann, weswegen bei var1 - var2 eigentlich was temporäres von Typ T<float, 3> rauskommen sollte und das sollte dann als argument für den anderen constructor bei der Klasse T2 genommen werden.
das problem ist außerdem noch, das wenn ich statt
T2 var3 = var1 - var2;jetzt
T2 var3(var1 - var2);schreibe dann nimmt er auch den expliziten constructor von T2 und subtrahiert wieder die zeiger voneinander.

-
Was sagt denn der Compiler, wenn du den operator t* weglässt? (btw, wozu benötigst du den überhaupt?)
-
FreakyBKA schrieb:
beim vereinfachen ist kein fehler passiert, habe es gerade nochmal durchgeschaut.
also ich hab mir jetz mal das mit explicit angeschaut, allerdings hab ich jetz ein anderes problem. nämlich:T2 var3 = var2 - var1;das funktioniert jetzt nicht mehr, warum auch nicht?
weil es gibt ja den copy-constructor über die klasse T, der das eigentlich abwickeln sollte.Ich wage mal zu behaupten, daß dann Dein Copy-Konstruktor nicht in Ordnung ist, bzw. nicht existiert. Oder aber Dein operator- gibt einen falschen Typ zurück.
//falscher Parameter oder nicht vorhanden T2(const T<float, 3>& src); //bzw. //gibt falschen Typ zurück. T<t,n> operator - (const T<t,n>& r);Offensichtlich scheint die Adressdifferenz, die durch das Subtrahieren der Zeiger entsteht, die einzige Variante zu sein, für die ein gültiger Konstruktor existiert (der jetzt aber explicit deklariert wurde).
-
also var1 - var2 sollte ein ergebnis vom typ T<float, 3> liefern, da der Subtraktions-Operator von T aufgerufen werden sollte und für T2 gibt es ja den Konstruktor
T2(const T<float, 3>& src);den Cast in (t*) brauch ich in dem programm, weil es bei mir funktionen gibt die diesen typ als argumenttyp haben, aber das ist ja für das problem irrelevant. der cast liefert quasi den zeiger der internen variable
t data[n];das sind aber wie gesagt alles nur details.
-
Aber genau dieser Cast scheint das Problem zu sein, weil jetzt außer deinem op- auch der eingebaute op- für Zeiger in Frage kommt für diesen Ausdruck
Wie gesagt, lass mal testweise diesen Operator weg.(wenn du an anderer Stelle unbedingt einen t* benötigst, ist vielleicht eine explizite Umwandlungsfunktion 't* data()' geeigneter als ein Umwandlungsoperator)
-
CStoll schrieb:
Aber genau dieser Cast scheint das Problem zu sein, weil jetzt außer deinem op- auch der eingebaute op- für Zeiger in Frage kommt für diesen Ausdruck
Wie gesagt, lass mal testweise diesen Operator weg.Aber der Cast DARF kein Problem sein, denn es ist standardisierte Regel, daß den passenden Typen priorität vor den implizit umzuwandelnden Typen eingeräumt wird. Selbst der eklige und antike MSVC 6.0 hier in der Firma macht das korrekt.
Ich schätze mal, daß nach wie vor entweder im Rückgabewert von operator- oder im Copy-Konstroktor ein Bock ist, und der Typ eben nicht passt ( vielleicht das kleine t vom Template-Type mit dem großen T der Klasse vertauscht o.ä.). Die Tatsache, daß es plötzlich gar keinen passenden Konstruktor mehr gibt, wenn man den Konvertierungskonstruktor mit den drei Float-Argumenten als explicit deklariert, ist ein weiteres Indiz dafür.
-
das problem ist ich kann den cast-operator nicht einfach weglassen, weil ich dann tausend anderen stellen fehlermeldungen bekomme, die eben genau diesen verwenden.
-
also T2 hat jetzt folgende Konstruktoren
explicit T2(float x = 0, float y = 0, float z = 0); T2(const T<float, 3>& src); T2(const T2& src);dennoch findet er bei der anweisung
T2 var1, var2; //... T2 var3 = var1 - var2;keinen passenden Konstruktor
-
Ehrlich gesagt gehen mir da die Erklärungen aus. Ich habe es mit der von Dir geposteten Templatisierung und Vererbung auf verschiedenen Compilern getestet, und bei mir wird immer der Operator und der Copy-Konstruktor aufgerufen. Bei camper scheint es auch zu laufen.
Das von Dir beschriebene Verhalten erreiche ich nur, wenn ich den Copy-Konstruktor auskommentiere oder einen anderen Rückgabewert für operator- angebe.