P
Halozination schrieb:
ok pumuckl habe mir geraden och einmal dein beispiel mit erklärung durchgelesen und glaube nun versteh ich es, echt ziemlich verrückt. Der compiler macht also aus myA ein B und myB ein C (ohne es ihm zu sagen) weil er sonst den < operator nicht ausführen kann und desshalb muss diese anderen constructor dabei haben
Ja, das sind einige Dinge, die da zusammenfinden. Was mein Beispiel eigentlich verdeutlichen sollte: der Compiler nimmt die beiden Typen, die er ja aus der Substitution der Templateparameter kennt, und versucht damit die Ausdrücke im Template zu compilieren.
Wenn er auf den operator< trifft (oder allgemein auf irgendeine Funktion), und die Argumenttypen passen nicht exakt zu einer Funktion, die es schon gibt, dann fängt er an, durch implizite Konvertierungen an den Typen rumzubiegen, bis er einen passenden Satz gefunden hat, der zu einer bestehenden Funktionssignatur passt. Das tut er übrigens nicht nur bei Templates, sondern eigentlich immer. Beispiel:
int foo(int);
short s;
foo(s); //der compiler findet kein foo(short), aber short kann er ja in int konvertieren...
Halozination schrieb:
man könnte es dem compiler aber eigentl auch sagen oder den vergleich direkt für A und B structs erstellen
klar könnte man. Aber man muss es ihm nicht direkt sagen, denn er kanns ja implizit machen. Das Beispiel zeigt übrigens eine der großen Gefahren von impliziten Konvertierungen, d.h. von Konstruktoren, die ein Argument haben und nicht als explizit deklariert sind, sowie von Konvertierungsoperatoren: Stell dir vor, A, B, C seien Bestandteile einer Bibliothek. Ein Anwender der Bilbiothek benutzt As und Bs in seinem Code und kennt vielleicht nichtmal das Interface von C, weiß also auch nichts von dem op<. Er vertippt sich und schreibt b<a - der Compiler schluckt das anstandslos, konvertiert wild an den Argumenten rum und macht einen Vergleich von dem der Entwickler nichtmal wusste dass er existiert. Sicher nicht das, was der Entwickler vorhatte...
Halozination schrieb:
noch eine frage:
B struct = i von der ursprüngl.
[cpp]
struct B {
int i;
B(int i) : i(i) {} //ich hätte geschrieben B(int j) {i = j}
};
...
B myB = 12; //myB (myB (12)
Was genau bedeutet ":" nach dem constructor? ich betrachte constructoren nur als funktion und deine schreibweise tut was genau? i(i) sieht für mich zieml. verwirrend aus.
Stichwort: initialisierungsliste. Ist dazu da, um Member und Basisklassen zu initialisieren, d.h. deren Konstruktoren aufzurufen.
Zugegegeben, hier siehts etwas verwirrend aus. Die Zeile könnte auch heißen
B(int iArg) : i(iArg) {}
- das bedeutet, dass der Member i mit dem iArg initialisiert wird.