Implizite Klassentypkonvertierung
-
Mit einer Konstanzen Referenz funktioniert es tatsächlich.
Wenn ich NUR das Objekt nehme leider nicht.#include <iostream> #include <iterator> #include <fstream> #include <sstream> #include <vector> #include <algorithm> #include <string> #include <utility> #include "faq.h" class FKEL { private: int x; int y; public: FKEL (FKEL &f) : x(f.x), y(f.y) {} FKEL (int a, int b) : x(a), y(b) {} FKEL (int a) : x(a) {} void setxy(int a, int b) { x = a; y = b; } std::pair<int, int> getxy(void) { return std::make_pair(x,y); } bool same_x(FKEL f) { return f.x == x; } }; using namespace std; int main(void) { FKEL f(4,5); FKEL u(f); pair<int, int> tag = u.getxy(); cout << tag.first << endl; cout << u.same_x(5,7) << endl; system("Pause"); }
-
Ja, diese implizite Umwandlung klappt auch nur mit Ein-Parameter-Konstruktoren. "x.same_x(5)" führt eine Typumwandlung von 5 in einen FKEL durch, "x.same_x(5,7)" sucht eine Methode, die zwei Parameter entgegennimmt - aber die existiert nicht.
-
Das hatte ich schon ausprobiert - auch hier gibts Fehler:
... using namespace std; int main(void) { FKEL f(4,5); FKEL u(f); pair<int, int> tag = u.getxy(); cout << tag.first << endl; cout << u.same_x(5) << endl; system("Pause"); } ...
Fehler:
40 C:\Dokumente und Einstellungen\Praktikant\Eigene Dateien\unProduktiv\readthis.cpp no matching function for call to `FKEL::FKEL(FKEL)'
note C:\Dokumente und Einstellungen\Praktikant\Eigene Dateien\unProduktiv\readthis.cpp:18 candidates are: FKEL::FKEL(int)
40 C:\Dokumente und Einstellungen\Praktikant\Eigene Dateien\unProduktiv\readthis.cpp initializing argument 1 of `bool FKEL::same_x(FKEL)' from result of `FKEL::FKEL(int)'
:p
-
Ja, der Copy-Ctor sollte auch eine konstante Referenz entgegennehmen - oder hast du vor, das kopierte Objekt nebenbei noch zu verändern?
-
Er übernimmt doch bei mir garkeine Referenz sondern ein direktes Objekt?!?
#include <iostream> #include <iterator> #include <fstream> #include <sstream> #include <vector> #include <algorithm> #include <string> #include <utility> #include "faq.h" class FKEL { private: int x; int y; public: explicit FKEL (FKEL &f) : x(f.x), y(f.y) {} FKEL (int a, int b) : x(a), y(b) {} FKEL (int a) : x(a) {} void setxy(int a, int b) { x = a; y = b; } std::pair<int, int> getxy(void) { return std::make_pair(x,y); } bool same_x(FKEL f) { return f.x == x; } }; using namespace std; int main(void) { FKEL f(4,5); FKEL u(f); pair<int, int> tag = u.getxy(); cout << tag.first << endl; cout << u.same_x(5) << endl; system("Pause"); }
-
Ich meinte nicht den int-Ctor, sondern den Copy-Ctor - und der übernimmt ganz klar eine Referenz:
777 schrieb:
explicit FKEL (FKEL &f) : x(f.x), y(f.y) {}
(und dieser Konstruktor hat das selbe Problem mit Referenz auf ein temporäres Objekt wie die same_x() in deinem ursprünglichen Code)
-
Oh... es funktioniert tatsächlich.
Doch der Konstruktor ist doch einfach zum initialisieren da.
Dann weiß ich nicht, warum es den Compiler stört, wenn man ein normales Objekt oder eine Nicht-Konstante Referenz übergibt.
Ist das einfach ein Mankel der Sprache, dass man das nicht darf oder hats bestimmte Gründe?
-
777 schrieb:
Dann weiß ich nicht, warum es den Compiler stört, wenn man ein normales Objekt oder eine Nicht-Konstante Referenz übergibt.
Ja, das ist die Hauptaufgabe des Konstruktors. Allerdings erwartet der Compiler bei der Übergabe als normale Referenz, daß der Parameter verändert werden könnte (in manchen Konstellationen macht das sogar Sinn - siehe z.B. std::auto_ptr). Darum kannst du als Referenz nur eine vollwertige Variable übergeben und keinen temporären Wert.
(und die Übergabe als Kopie an den Copy-Ctor würde zu einer Endlos-Rekursion führen - um den Parameter anzulegen, ruft der Copy-Ctor sich selber auf)
-
Aber "same_x" hat sich ja auch darüber beschwert, dass ich eine Referenz und keine Kopie übergeben habe.
Und das Elementfunktionen an sie übergebene Objekte nicht ändern dürfen steht in meinem Buch nicht -
-
Klar dürfen Elementfunktionen die übergebenen Objekte ändern (solange diese nicht als const übergeben wurden). Und dein Problem hat auch gar nichts mit Methoden zu tun, das funktioniert genauso (nicht) bei normalen Funktionen:
void func(int& param) { ... } int main() { int i=0; func(i);//klappt problemlos double d=0.0; func(d);//klappt nicht - siehe unten }
Der Punkt ist: Wenn du einen Parameter als (normale) Referenz übergibst, vermutet der Compiler, daß die Funktion diesen Parameter ändern will - und daß das aufrufende Programm an dieser Änderung interessiert ist. Darum kannst du dort nur eine Variable (genauer: einen LValue) übergeben, der einen exakt passenden Typ hat. Typumwandlungen durch einen Konvertierungs-Konstruktor - oder die eingebaute Umwandlung double nach int - erzeugen aber keinen LValue, sondern nur einen temporären Wert, der am Ende der Ausdrucks wieder ins Nirvana verschwindet - damit wären alle Änderungen, die die Funktion vorgenommen hat, hinfällig.
Bei der Übergabe als konstante Referenz gibt es keine Änderungen an der Variablen (wenn doch, verlässt du den Bereich definierten Verhaltens), also reicht die temporäre Variable völlig aus für die Zwecke der Funktion. Bei der Übergabe als Wert wird eine eigenständige Kopie des Wertes erzeugt - und das Problem damit weitergeleitet an deinen Copy-Ctor.
PS: Was mir gerade auffällt - den Copy-Ctor 'explicit' zu definieren macht wenig Sinn
-
aaaaaaaaaaaaaachsooo....
Temporäre Objekte dürfen nicht geändert werden.
Dann leuchtet mir das ein.