Buchempfehlung C++ templates + Vererbung
-
Wer kann mir ein Buch empfehlen was auf typische Probleme im Zusammenhang template BasisKlasse und Vererbung behandelt.
Hab eine Basisklasse die arithmetische op definiert.
z.B. op+=( const Vector<U>& src) und op+=( const U& zahl)
in der abgeleiteten Klasse kann der Compiler die Typen nicht richtig auflösen.
Er ruft dann op+=( const U& zahl) mit U = NumericVector<float> auf.Wenn ich in der abgeleiteten Klasse alle op nochmal definiere ist wieder alles schön.
Sollte man grundsätzlich auf eins von beidem verzichten oder geht da was quer in meinem Kopf???

Vielen Dank
-
Hallo da draußen, es wäre echt toll wenn jemand was sagen könnte.
Und fallst Du denkst, schau doch erstmal bei den Buchempfehlungen nach, glaub mir ich hab es getan.
Vielleicht gibt's ja auch noch mehr Leute die Bücher lesen und es steht noch nicht alles drin. oder ist dieses Problem so dämlich das man sich damit garnicht erst beschäftigen sollte?mfG, cris
-
cris492 schrieb:
Er ruft dann op+=( const U& zahl) mit U = NumericVector<float> auf.
Kann ich ehrlich gesagt nicht nachvollziehen. U sollte eigentlich was sein?
Mach mal ein Minimalbeispiel (also keine Implementationsdetails), mit Basisklasse und abgeleiteter Klasse, dem op+= und einem Aufruf davon, wo etwas nicht so läuft, wie du dir das vorstellst.
-
groovemaster schrieb:
cris492 schrieb:
Er ruft dann op+=( const U& zahl) mit U = NumericVector<float> auf.
Kann ich ehrlich gesagt nicht nachvollziehen.
Ich gehe mal davon aus, dass der OP in etwa folgende Situation hat:
template <class T> class Vector { public: template <class U> Vector<T>& operator+=(const Vector<U>& other) { cout << "Hallo" << endl; return *this; } template <class U> Vector<T>& operator+=(const U& other) { cout << "Huhu" << endl; return *this; } }; template <class T> class NumericVector : public Vector<T> {}; int main() { NumericVector<float> x, y; x += y; }Ausgabe soll sein: "Hallo" ist aber natürlich "Huhu".
OP:
Falls ich mit dem Beispiel falsch liege, bitte unterbrich mich jetzt
Der Grund für das Verhalten hat nicht direkt etwas mit Vererbung zu tun. Vielmehr mit der Art und Weise wie Templates instanziiert werden und wie Überladung in C++ funktioniert.
Für x += y gibt es prinzipiell zwei mögliche Überladungen. Entweder operator+=(const Vector<U>& other) oder operator+=(const U& other). Beide müssen zuvor instanziiert werden. Dazu muss ein passender Typ für U hergeleitet werden.
Im ersten Fall ist U = float. Im zweiten ist U = NumericVector<float>. Also hast du letztlich:
operator+=(const Vector<float>& other)
operator+=(const NumericVector<float>& other)Jetzt kommen die ganz normalen Überladungsregeln ins Spiel. Beide Überladungen sind aufrufbar. Die zweite wird aber bevorzugt, da sie ein "exact match" ist, wohingegen die erste eine "derived-to-base"-Konvertierung erfordert.
Lösungen gibt es viele. Von der Umstellung des Design bis zur Verwendung von boost::enable_if
Buchempfehlung zum Thema Templates ist einfach:
"C++ Templates: The Complete Guide" von David Vandevoorde und Nicolai Josuttis.
-
Jawohl, das ist so genau mein Problem.
für den Compiler passt halt U = NumericVector<float> besser als
Vector<T> = NumericVector<T> with T = float auch wenn es genau das ist was ich ja eigentlich will.Vielen Dank für den Tip!
Über C++ Templates hab ich auch schon nachgedacht, war mir aber unsicher ob ich derartig schwere Lektüre schon verarbeiten kann.
Hab inzwischen mein Design auf Templates ohne Vererbung umgestellt,
ein Freund gab mir den Tip Vererbung doch eher sparsam einzusetzen.Würde die von Dir erwähnte "derived-to-base"-Konvertierung einen Konvertierungskonstruktor derived to base sinnvoll machen?
Wenn ich den nicht schreibe erzeugt der Compiler selber einen, bzw. macht einen impliziten Cast, oder?Vielen Dank.