Linker-Problem bei Template-Methode
-
edit> Linker Problem geloest, es bleibt ein grundsaetliches Problem bei
Verwendung von Templates..vielen Dank fuer euere Hilfe bisher !Hallo,
Ich habe eine verkettete Liste geschrieben, die Template-Objekte aufnehmen soll.Dazu habe ich (nun) den Datenknoten zu einer Template Klasse (template <class T>
class Component{..}) gemacht.In der Main-Funktion wird ein spezifisches Template-Objekt (Component<Typ1>)
erzeugt. Dies geschieht durch einen Konstruktor der den jeweiligen Typ übergeben
bekommt und in T speichert.
Das funktioniert auch soweit.
Nun zum Problem:
Die Liste sowie der Kopf- und Endknoten sind keine Template-Klassen. Da dort
lediglich die Methode add() mit einem template-Objekt in Berührung kommt, habe
ich die add Funktionen zu template <class T> Funktionen gemacht.Also zB in HeadNode:
class Headnode : public Node { public: .. template <class T> Node * add(Component<T> *t); .. }Auch Endknoten und Liste sind so aufgesetzt.
Ebenso die Kalsse Node, nur ist diese Methode auf = 0 gesetzt, damit Node zu
einem ADT wird, da diese nur von den erbenden Klassen überschrieben werden
soll.Das Problem ist: Wenn ich nun das in main erzeugte Objekt an die Liste übergeben
will, scheint es ein Problem zu geben.
Der Linker sagt er könne die Referenz auf Node * Node::add(Component<Typ1>
nicht auflösen.
Die add-Methoden sehen, wie erwähnt alle wie folgt aus:add(Component<T> *t){...}
das soll so sein, weil ich dieser add-Methode beliebige Objekte übergeben
möchte, die dann entweder delegiert oder in einem DatenElement gespeichert
werden sollen.Wo könnte das Problem liegen?
-
Hast du die add-Memberfunktion in der Header-Datei implementiert? Oder in einer cpp Datei? Muss nämlich in den Header rein.
-
Hi,
also der einfachheithalber sind Deklaration und Methoden alle Knoten und der
Liste zur Zeit in einer Header-Datei untergebracht die in main.cpp eingebunden
wird. Allerdings sind die add-Methoden, die einen Datenknoten erstellen und
diesen den Wert übergeben ausserhalb der Klassendeklaration untergebracht.Also so bei HeadNode und der Liste (die nur delegieren)
<nodes.hpp>class HeadNode{ public: .. template <class T> Node * add(DataNode<T> *t){thisNext->add(t)} .. private: Node *thisNext; }Und bei TailNode und DataNode (da diese beiden ja Knoten hinzufügen sollen)
class TailNode : public Node{ public: .. template <class T> Node * add(DataNode<T> *t); .. private: Node *thisNext; T *thisData // nur im DatenKnoten } template <class T> Node * TailNode::add(DataNode<T> *t){ .. DataNode *newDataNode = new DataNode; // Kopier-Konstruktor dann Kopie an Liste anfügen .. }Hatte mich eben unglücklich ausgedrückt, es soll ein Datenknoten übergeben
werden, von dem eine Kopie um entsprechende Referenzen ergänzt in die Liste
eingefügt werden. Also nicht add(Component<T> *t) sondern add(DataNode<T> *t).
DataNode ist die Template-Klasse, die die übergebenen Objekte (typ1, typ2 etc)
in T ablegt.
-
Es geht weder um HeadNode::add noch um TailNode::add. Der Linker kann Node::add nicht finden. Was ist damit?
-
Die Node-Klasse soll ein ADT für die anderen Knotenklassen sein.
Implementation ist wie folgt:
class Node{ public: .. template <class T> Node * add(DataNode<T> *t) = 0; .. }Das Schlüsselwort virtual hat der Compiler, in ähnlichem Zusammenhang, schonmal
angemeckert. Gibt es da eine Besonderheit bei Template-Methoden?DataNode erbt von Node, ist aber eine Template-Klasse:
template <class T> class DataNode : public Node{ .. }Die Methode add(DataNode<T> *t) soll von allen erbenden Klassen überschrieben werden.
-
Nachtrag:
Das Schlüsselwort virtual habe ich nicht, wie vorher angegeben, in Node oder den
erbenden Klassen angegeben.
Schreibe ich virtual vor template, teilt der Compiler mit, dass virtual nur auf
Fuktionen angewandt werden darf. Schreibe ich das Wort vor den Rückgabewert der
Methode, mahnt der Compiler 'illegal use of ''virtual'.
-
virtual ist nicht in verbindung mit templates erlaubt!
-
Ich habe ein weiteres Verständnis-Problem bzgl. Templates was zu einem
Link-Fehler führt:Ich erzeuge in main einen Data-Knoten vom Typ1 und übergebe diesem ein Objekt
von Typ1, welches in T gespeichert wird:.. DataNode<Typ1> *test = new DataNode<Typ1>(obj_typ1); liste.add(test);Die Zuweisung alleine geht, das hinzufügen zur liste allerdings nicht..
Link Fehler: undefined reference to Node::add<typ1>(DataNode <typ1> *)Es soll für alle T-Elemente (typ1, typ2..) die Methode ..
template <class T> .. add(DataNode<T> *t){..}verwendet werden. Rückgabewert ist void für die Liste, Node für alle anderen.
Die Liste erbt nicht von Node.Die Methode ist in Node deklariert und soll eigentlich überschrieben werden:
class Node{ .. template <class T> Node * add(DataNode<T> *t) = 0; .. }Wie schaffe ich das alle DataNode-Typen derselbe Methode add(DataNode<T> *t)
zugewiesen werden?Vielen Dank für euere Hilfe!
-
class Node{ .. template <class T> Node * add(DataNode<T> *t) = 0; .. }dies würd ich am ehesten als groben unfug bezeichnen, da "=0" nur mit "virtual" zusammen funktioniert. Und da virtual nicht zusammen mit templates funktioniert ists essig mit überschreiben.
-
Danke fuer euere Hilfe!
Ja das habe ich schon befuerchtet. Ich habe versucht der Template-Methode add die
virtual Deklaration irgentwie aufzuzwaengen. Denn ohne diese Deklaration habe ich
ein Problem.Ich brauche Node und dessen Methode add(DataNode<T> *t) als allgemeine Referenz
auf ein Knotenobjekt.Gibt es eine Moeglichkeit, wie ich auf die Methode add(DataNode<T> *t) von der
erbenden Klassen zugreifen kann?In Node ist jetzt add(DataNode<T> *t){}, damit kompiliert das Programm und die
DatenKnoten werden delegiert. Allerdings nicht hinzugefuegt, da die nicht als
virtuell deklarierbare Methode von Node aufgerufen wird und nicht die entsprechende
des Objekts.