2009-10-27 10 views
2

Je ne suis pas un programmeur C++ expérimenté et j'ai des problèmes de compilation. J'ai une classe Heap qui utilise un modèle:C++ classe avec les templates erreur de compilation

template <class T> 
class Heap 
{ 
    public: 
    Heap(const vector<T>& values); 

    private: 
    vector<T> d; 

    // etc. 
}; 

Et puis dans un fichier de mise en œuvre cloisonnée:

template <class T> 
Heap<T>::Heap(const vector<T>& values) 
{ 
d = values; 

for (unsigned int i = d.size()-1; i > 0; i--) Heapify(ParentIndex(i)); 
} 

// ... more implementation code ... 

Et enfin un fichier main.cc:

int main (int argc, char *argv[]) 
{ 
    vector<int> in; 
    unsigned int i; 

    while (cin >> i) in.push_back(i); 
    Heap<int> h = Heap<int>(in); 

    return 0; 
} 

I obtenir ces erreurs de compilation:

g++ -Wall -I/opt/local/include -c -o main.o main.cc 
g++ -Wall -I/opt/local/include -c -o heap.o heap.cc 
g++ -Wall -o heap main.o heap.o 
Undefined symbols: 
    "Heap<int>::Heap(std::vector<int, std::allocator<int> > const&)", referenced from: 
     _main in main.o 
ld: symbol(s) not found 
collect2: ld returned 1 exit status 
make: *** [heap] Error 1 

Pourquoi cela ne compile-t-il pas? Je pense que le lieur dit qu'il ne peut pas trouver le constructeur, mais je sais qu'il a fait le fichier objet.

+1

Le constructeur Heap est-il défini dans un fichier séparé? Cela ne fonctionne pas très bien avec les modèles. –

Répondre

8

Les modèles doivent être définis à 100% dans le fichier d'en-tête. Si vous avez votre implémentation Heap<T> dans un fichier .cc/.cpp qui est le problème. Déplacez tout le code dans le fichier d'en-tête et il devrait résoudre votre problème.

+0

Vous pouvez également les garder physiquement séparés par #including les implémentations dans l'en-tête – Cogwheel

+0

@Cogwheel, true, mais l'inclusion d'un fichier .cpp est généralement un code de mauvaise connexion. Je préfère soit 1) tout dans un .h ou 2) mettre du code dans un fichier .inl. L'extension de fichier différente rend beaucoup plus clair ce que l'intention est – JaredPar

+0

@JaredPar, oui. J'utilise habituellement .inl. – Cogwheel

3

Selon la norme du C, vous pouvez utiliser le mot-clé export ainsi:

export template<typename foo>... 

Cependant, la plupart des compilateurs ne supportent pas cela. La FAQ C++ a plus d'informations: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.14

Voir la réponse de JaredPar pour quelque chose qui est réellement fiable.

+0

"l'exportation" était l'une de ces choses que le Comité de normalisation est resté sans expérience et cela se voit. C'est difficile à mettre en place, et ne semble pas faire ce que tout le monde veut vraiment de toute façon. –