template Funktion in Mutterklasse
-
Hallo zusammen,
ich habe zwei Klassen A und B. Klasse B erbt von Klasse A.
In Klasse A habe ich eine template-Funktion implementiert, die ich aus einer Funktion aus Klasse B aufrufen moechte. Dies funktioniert aber nicht, beim linken kommt eine Fehlermeldung:
undefined reference to `void A::swap<int>(&int, &int)'
Die Funktion ist wie folgt deklariert:
template <class T> void A::swap(T &x, T &y)(Funktion nur zum Testen der Funktionalitaet so wie oben implementiert)
Rufe ich die template-Funktion aus einer Funktionen der Mutter-Klasse auf, geht dies aber. Sobald man dies tut, also die Funktion in der Mutterklasse aufruft, kann ich auch die template-Funktion in der Tochter-Klasse aufrufen, allerdings nur mit dem Datentyp, den auch die Mutterklassen-Funktion benutzt hat.
Meine Fragen:
- Ist es prinzipiell moeglich, die template-Funktion in der Tochterklasse aufzurufen?
- Warum ist es scheinbar so, dass der Linker die Funktion "kennt", sobald man sie in der Mutterklasse mit einem speziellen Datentyp auruft?
Viele Gruesse
Joachim
-
Ich denke das Problem was hier zum Tragen kommt ist, dass der Compiler bei Benutzung eines Templates die komplette Definition kennen muss. Sonst weiss er nicht, in welcher Übersetzungseinheit er den Code ablegen resp. suchen soll.
Durch den Aufruf der Templatefunktion in der Mutterklasse (wo die Definition anscheinend bekannt ist) wird jetzt aber eine Instanz des Templates auf dem Typ erzeugt, diese Instanziierung kann dann auch von anderen Übersetzungseinheiten gefunden werden.
Lösung: Templates _immer_ komplett im Header definieren.
-
Bei einem Template erzeugt der Compiler zunächst keinen Code, den der Linker finden könnte (weil er gar nicht weiß, mit welchen Typen er letztendlich arbeiten soll). Erst wenn das Template instanziiert (=verwendet) wird, kann er den nötigen Maschinencode zusammensetzen - aber dazu benötigt er den Quelltext.
Jetzt nehmen wir dein Beispiel:
A und B werden unabhängig voneinander übersetzt (vermute ich mal).
Solange du in der A.cpp bist, hast du den Quelltext von swap() vor Ort verfügbar, also können bei Bedarf die richtigen Instanziierungen angelegt werden.
In der B.cpp hast du jedoch nur die Deklaration der Methode - der Compiler ist zufrieden und sagt dem Linker, daß er die int-Version von swap benötigt. Wenn A.cpp diese bereitgestellt hat, ist alles gut; wenn nicht, beschwert sich der Linker.Lösung des Dilemmas:
Templates gehören (fast) IMMER direkt in die Headerdateien - dann hat der Compiler in jeder Übersetzungseinheit den Quellcode zur Hand, um die benötigten Instanziierungen vorzunehmen.
-
Vielen Dank fuer Eure schnellen Antworten. Mein Problem wurde dadurch behoben.
Viele Gruesse
Joachim