Template, Veraerbung
-
Hallo Zusammen,
ich erhalte immer einen Linkerfehler
[Linker error] Unresolved external 'X<unsigned char>:Start ref...
...Meine Klassenstruktur:
Jede Klasse befindet sich in einer seperaten Header Datei.
Die Klasse X ist Abstrakt und Basisklasse von Y und Z.template <class f> class X { public: virtual void Start() = 0; }; template <class f> class Y : public X<f> { public: virtual void Start(); }; template <class f> class Z: public X<f> { public: virtual void Start(); };
Hoffe jemand kann mir Helfen. Oder muss ich die Templates anders definieren.
Ohne Template Funktioniert alles wunderbar. Nur wenn ich die Templates einbinde.Danke!!!
-
hast du die Start Elementfunktion in den abgeleiteten Klassen irgendwo definiert? Poste mal bitte den ganzen Fehler.
-
Der ganze Fehler lautet:
[Linker Fehler] Unresolved external 'X<unsigned char>::Start()' referenced from C:\C\spv\HAUPTFENSTER.OBJ
In den Abgeleiteten Klassen habe ich die Funktionen folgendermaßen definiert:
template <class f> void Y<f>::Start() { cout << "Hallo\n"; }
Wie gesagt ich Habe mit den Klassen und den Methoden gearbeitet und als Datentyp "unsigned char" verwendet. Nur möchte ich die Klassen auch mit anderen Datentypen auch nutzen.
Programmierumgebung Borland C++ Builder 5.0
-
das Problem scheint an dem Builder zu liegen, denn die Syntax ist richtig.
-
Hallo,
mach mal die Memberfunktionsdefinitionen mit in die Header oder includiere
unter deine Headerfile am Ende die Implementationsdatei deiner Memberfunktionen.mfg
v R
-
Hallo Zusammen,
danke für die Hilfe. Es Funktioniert, ich habe
die Memberfunktionen in die Herderdatei kopiert
wie virtuell Realisticer gesagt hat. Scheinbar liegt
es am C++ Builder Kompiler.Danke!!!
-
Das liegt nicht am Builder, das ist bei MSVS genau so. Du musst wenn du die Unterteilung in .h und .cpp haben willst in der Header bei der Klassendeklaration "export" davor schreiben:
export template <class f> class X {...}
Der MSVS unterstützt "export" nicht. Beim Builder weiß ich es nicht, das musst du in der Referenz nachsehen. Ansonsten bei templates alles in die Headerdatei, so wird es von allen Compilern angenommen.
Code-Hacker
-
Von den Borland Compilern unterstuetzt export bis jetzt nur der, welcher beim
BuilderX mitgeliefert wird.mfg
v R
-
Code-Hacker schrieb:
Das liegt nicht am Builder, das ist bei MSVS genau so. Du musst wenn du die Unterteilung in .h und .cpp haben willst in der Header bei der Klassendeklaration "export" davor schreiben:
export template <class f> class X {...}
Der MSVS unterstützt "export" nicht. Beim Builder weiß ich es nicht, das musst du in der Referenz nachsehen. Ansonsten bei templates alles in die Headerdatei, so wird es von allen Compilern angenommen.
Code-Hacker
erzähl bitte keinen Unsinn. Das export Schlüsselwort ist für Funktion-Templates und non-inline Elementfunktion-Templates gedacht. Außerdem läßt sich mit VC7.1 folgendes problemlos kompilieren
//h template<class T> class B { public: void foo(); }; //cpp template<class T> void B<T>::foo() { } //... B<int> b; n.foo();
-
Genau sowas lies sich bei mir mit dem VC7.1 nicht kompilieren. Da kam der selbe Fehler wie im Builder.
In einem Buch habe ich gelesen das die Aufteilung nicht in der ursprünglichen Natur läge musste dieses Schlüsselwort eingeführt werden um dem Compiler mitzuteilen das sich Template-Definition und Template-Methoden-Definitionen in unterschiedlichen Dateien befinden, dazu ein Beispiel:export template<class Typ, int S> class Feld { blalbla... };
Habe eben aber nochmal in "Die C++-Programmiersprache" geguckt und mich eines besseren belehren lassen. Muss ich nochmal gucken ob ich da falsch gemacht habe bei meinem Template. Mich wundert nämlich das es, wenn ich es nur in der .h habe, funktioniert und getrennt nicht übersetzt wird.
Code-Hacker
-
Code-Hacker schrieb:
Genau sowas lies sich bei mir mit dem VC7.1 nicht kompilieren. Da kam der selbe Fehler wie im Builder.
In einem Buch habe ich gelesen das die Aufteilung nicht in der ursprünglichen Natur läge musste dieses Schlüsselwort eingeführt werden um dem Compiler mitzuteilen das sich Template-Definition und Template-Methoden-Definitionen in unterschiedlichen Dateien befinden, dazu ein Beispiel:export template<class Typ, int S> class Feld { blalbla... };
Habe eben aber nochmal in "Die C++-Programmiersprache" geguckt und mich eines besseren belehren lassen. Muss ich nochmal gucken ob ich da falsch gemacht habe bei meinem Template. Mich wundert nämlich das es, wenn ich es nur in der .h habe, funktioniert und getrennt nicht übersetzt wird.
Code-Hacker
Du hast schon recht mit dem Schluesselwort export.
Andernfalls, muss eine template-Funktion in jeder Implementationsdatei
definiert werden, oder es kann sein, dass der Compiler die Definition einer
solchen Funktion nicht findet und dann meldet sich der Linker.mfg
v R
-
Stimmt. Kompilieren geht, Linken geht nicht.
Code-Hacker
-
falls du das kleine Beispiel aus meinem vorherigen Posting meinst, dann geht beides sonst hätte ich es erwähnt.
-
Also ich habe eben mit VS7.1 dein Template benutzt und das versucht. Funktionierte nicht. Es kam folgender Fehler:
CPPTests error LNK2019: Nicht aufgelöstes externes Symbol '"public: void __thiscall B<int>::foo(void)" (?foo@?$B@H@@QAEXXZ)', verwiesen in Funktion '_main'
So sehen die Dateien aus:
test.cpp:#include "test.h" template<class T> void B<T>::foo() { }
test.h:
template<class T> class B { public: void foo(); };
main.cpp
#include <iostream> #include "test.h" int main() { B<int> n; n.foo(); std::cin.get(); }
Mache ich irgendwas falsch???
EDIT:
Wenn ich test.h wie folgt ändere funktioniert es:template<class T> class B { public: void foo(); }; template<class T> void B<T>::foo() { }
Code-Hacker
-
füge in die main.cpp folgendes ein
#include "test.cpp"
-
Das ist aber übler Stil und hat nichts mit export zu tun. cpps gehören nicht inkludiert.
-
operator void schrieb:
Das ist aber übler Stil und hat nichts mit export zu tun. cpps gehören nicht inkludiert.
Die Endung .cpp ist schlecht gewählt, aber so ein #include ist gängige Praxis.
-
Ich würde als Endung *.inl vorschlagen.
-
Shlo schrieb:
füge in die main.cpp folgendes ein
#include "test.cpp"
Das ist exakt _das_ was CodeHacker und ich sagten und _kein_ Unsinn gewesen!
Wenn du kein export hast, benoetigst du die Implementation der templates in
jeder Implementationsdatei, in welcher du die Templates einsetzt, nicht mehr
und nicht weniger hab ich gesagt.mfg
v R
-
Es gibt noch eine Möglichkeit, die explizite Instantiierung heisst.
//die Zeile gehoert zu der Cpp-Datei template class B<int>;