2011-07-03 3 views
1

Salut tout le monde Je voulais juste m'exercer à un modèle C++ mais j'ai des erreurs de liens. Est-ce que quelqu'un peut m'aider s'il vous plaît? Voici mon code:Classe de modèle C++ Problème

// File: MyClass.h 
#ifndef _MYCLASS_H 
#define _MYCLASS_H 
template<class T> class MyClass { 
T value; 
public: 
MyClass(T v); 
~MyClass(); 
}; 
#endif // _MYCLASS_H 

// File: MyClass.cpp 
#include "MyClass.h" 
template<class T> MyClass<T>::MyClass(T v) { 
value = v; 
} 
template<class T> MyClass<T>::~MyClass() { 

} 

// File: main.cpp 
#include "MyClass.h" 
int main() { 
MyClass<int> test(10); 
return 0; 
} 

est ici la sortie de ligne de commande:

g++ main.cpp -c 
g++ MyClass.cpp -c 
g++ main.o MyClass.o -o Out 
main.o: In function `main': 
main.cpp:(.text+0x1a): undefined reference to `MyClass<int>::MyClass(int)' 
main.cpp:(.text+0x2b): undefined reference to `MyClass<int>::~MyClass()' 
collect2: ld returned 1 exit status 
make: *** [all] Error 1 

Comme vous pouvez le voir, je suis en utilisant Ubuntu 10.04 et compilateur GNU C++. Est-ce qu'il me manque quelque chose dans ce code?


Merci pour les réponses. Cela fonctionne mais n'existe-t-il pas une meilleure façon de protéger le code? Par exemple, que se passe-t-il si je veux créer une bibliothèque non-opensource ?! Je veux exporter le code vers une bibliothèque statique. et lier la bibliothèque à d'autres projets ...

+0

'MyClass.cpp' et' main.cpp' sont compilés séparément (différentes unités de traduction), donc quand votre compilateur compile le 'MyClass.cpp' il ne sait pas pour quels arguments il doit être instancié. vous devez déplacer la définition et la déclaration vers 'main.cpp'. –

Répondre

5

Vous devez mettre le modèle complet dans l'en-tête. Le compilateur doit voir le corps des méthodes de modèle sur le site d'instanciation de modèle - main.cpp dans votre cas. Voir, par exemple, C++ FAQ.

+0

À droite, et je suggère de renommer 'MyClass.cpp' en' MyClass_impl.h' et '#include" MyClass_impl.h "' à la fin de 'MyClass.h'. Cela permet de maintenir la déclaration et la mise en œuvre dans des fichiers séparés pour faciliter la lecture. –

1

Vous devez placer des classes de modèle et des méthodes en ligne dans des fichiers d'en-tête. Vous ne pouvez pas séparer la définition et la mise en œuvre dans leur cas.

1

@Nikolai N Fetissov a la bonne solution. Je voudrais ajouter à ce que une belle façon de le faire, si vous voulez garder la mise en œuvre et définitions de fonctions basés sur des modèles séparé est que vous pouvez mettre les implémentations dans MyClass.hxx et l'inclure à la fin de votre MyClass.h

// File: MyClass.h 
#ifndef _MYCLASS_H 
#define _MYCLASS_H 

template<class T> class MyClass 
{ 
    T value; 
public: 
    MyClass(T v); 
    ~MyClass(); 
}; 

#include "MyClass.hxx" /// <--- like this 
#endif // _MYCLASS_H 
0

Il est important de se rappeler ce qu'est un modèle. C'est un modèle pour générer du code si nécessaire; ce n'est pas le code lui-même. Par conséquent, déclarer une implémentation de classe et d'écriture de modèle pour ces méthodes ne génère aucun code objet pour cette classe; il fournit simplement un modèle pour le faire si nécessaire.

Lorsqu'une classe de modèle est instanciée avec un argument réel, le compilateur génère le code à partir de la classe de modèle. Pour ce faire, il doit être capable de voir les modèles. Mais puisque vous n'avez que le fichier .h et l'implémentation des méthodes dans le fichier .cpp, le compilateur ne pourra pas générer le code objet pour les implémentations de la fonction. Ensuite, lorsque l'éditeur de liens recherche ces définitions, il ne les trouve pas. Tout cela est une façon longue d'obtenir le même résultat que les autres réponses - vous devez mettre l'implémentation dans le fichier d'en-tête avec la déclaration de classe. Mais cela peut aider à savoir pourquoi.