Verknüpfung von Vorlagen mit g++
Ich bin Implementierung einer hash-Tabelle und verkettete Liste in C++ (kein STL - fragt nicht), templates zu verwenden, und ich bin in Probleme laufen, verbindet Sie mit g++. Wenn ich #include alle meine .cpp-Dateien zusammen, alles funktioniert, also mein code funktioniert auf jeden Fall, es ist nur die Verlinkung, die ist tripping me up.
Lese ich das bit in der GCC-Dokumentation über template-Instantiierung, war sich aber nicht sicher sind, wie Sie es anwenden.
Mein problem:
Ich habe eine HashMap<T>
und HashEntry<T>
für meine hash-Tabelle (<T>
ist die Wert - meine Schlüssel sind std::string
s). Meine verlinkte Liste hat LinkedList<T>
und Node<T>
(wo <T>
ist der Wert).
In meinem hash-map, die ich habe:
template <class T> class HashMap {
...
private:
LinkedList< HashEntry<T> >** buckets;
}
Gibt mir eine verknüpfte Liste von HashEntry<T>
s.
In einer separaten Datei, ich habe meine Link-Liste Deklaration der Klasse:
template <class T>
class Node {
...
private:
T data;
}
template <class T> class LinkedList {
...
private:
Node<T> * first;
}
Dann, wenn ich versuche zu verknüpfen, alles (nach dem kompilieren mit g++ -c -frepo *.cpp
), erhalte ich:
g++ -frepo -o app LinkedList.o HashMap.o
[...unrelated errors about not having a main method - they go away when I link that in]
HashMap.o: In function `HashMap<int>::~HashMap()':
HashMap.cpp:(.text._ZN7HashMapIiED1Ev[HashMap<int>::~HashMap()]+0x65): undefined reference to `LinkedList<HashEntry<int> >::~LinkedList()'
HashMap.o: In function `HashMap<int>::insert(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)':
HashMap.cpp:(.text._ZN7HashMapIiE6insertESsi[HashMap<int>::insert(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)]+0xff): undefined reference to `Node<HashEntry<int> >::setData(HashEntry<int>)'
Googeln um, ich habe gesehen, Vorschläge für die Deklaration die explizite template-Typen, die mein Programm verwendet. Dies funktioniert für die HashMap
und HashEntry
(ich Hinzugefügt (template class HashMap< int >
und template class HashEntry< int >
.
Jedoch kann ich nicht herausfinden, wie diese Arbeit zu machen für LinkedList
und Node
Klassen, da die template-Instanzen sind von HashEntries<int>
. ABER, ich kann nicht, dass in der LinkedList.h
- Datei, da es #include
d von meinem Hash-Tabellen. Ich konnte auch nicht eine erweiterte/extern-Deklaration für Sie tätig.
Ich bin mir sicher, dass es etwas relativ einfaches, das mir fehlt, um all diese Arbeit. Irgendwelche Tipps?
- Gibt es eine definition der
LinkedList
Destruktor überall? OderNode<...>::setData()
? - Wahrscheinlich in keinem Zusammenhang, aber gibt es irgendeinen Grund Sie nicht mit etwas, was wie zu machen, waf, SCons, etc.?
- Richtig, meine HashMap verwendet die LinkedList (für die Verkettung), und ich habe eine
#include "LinkedList.h"
an der Spitze meiner Datei. - Ich habe meine ~LinkedList() und setData in die .cpp-Datei (
template <class T> LinkedList<T>::~LinkedList()
). Wieder, es kompiliert wird, wenn ich #include alle meine .cpp-Dateien zusammen. Keine build-system - nur versucht, es zu erhalten zu arbeiten, von Grund auf für jetzt.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn Sie template-Klassen, ist es nicht eine gute Idee, um Sie in .cpp-Dateien, und kompilieren Sie separat. Der richtige Weg ist, um Sie in .h-Dateien (beide Deklaration und definition) und fügen Sie Sie, wo Sie Sie benötigen.
Der Grund dafür ist, dass die Vorlagen nicht wirklich kompiliert werden, es sei denn, Ihre template-Argumente definiert sind.
(Absichtlich vermieden zu erwähnen, die
export
Stichwort.)export
Ding immer entfernt in C++0x... ach ja richtig 😛 +1Es sieht aus wie du bist Definition der template-Klasse Mitglieder in LinkedList.cpp. Vorlagen müssen in der Regel komplett und genau definiert sein (nicht nur deklariert), in der .h-Datei. Für Möglichkeiten das zu umgehen, siehe speichern von C++ template-Funktionen in einem .cpp-Datei. Aber ich würde es vermeiden-es verursacht mehr Probleme, als es Wert ist.