2010-10-25 2 views
2

J'ai créé un exemple ci-dessous pour illustrer le problème que je rencontre. Fondamentalement, quand je sépare une classe de modèle dans un fichier séparé .h/.cpp, j'obtiens des symboles non résolus pour le constructeur. En utilisant un seul fichier, il compile bien. Qu'est-ce qui cause ça?La séparation d'une classe de modèles en plusieurs fichiers génère des problèmes de liaison

fruits.cpp:

#include "apple.h" 

class FruitsDB { 
    public: 
     void addApple(); 
}; 

void FruitsDB::addApple() { 
    Apple<int> m; 
} 

int main() { 
    FruitsDB fruits; 
    return 0; 
} 

apple.h:

template <typename T> 
class Apple { 
    public: 
     Apple(); 
     ~Apple(); 
}; 

apple.cpp

template <typename T> 
Apple<T>::Apple() { 
} 

template <typename T> 
Apple<T>::~Apple() { 
} 

Cela produit l'erreur du compilateur:

g++ -c -o fruits.o fruits.cpp 
g++ -c -o apple.o apple.cpp 
g++ -Wall -ggdb fruits.o apple.o -o fruits 
Undefined symbols: 
    "Apple<int>::Apple()", referenced from: 
     FruitsDB::addApple()  in fruits.o 
    "Apple<int>::~Apple()", referenced from: 
     FruitsDB::addApple()  in fruits.o 
ld: symbol(s) not found 

Je pensais que c'était mon code qui causait le problème, mais la consolidation des fichiers ne pose pas de problème. Je suppose que j'ai besoin d'inclure un fichier quelque part où je ne suis pas. Je suis totalement perdu.

Note: Ajout template <> Apple<int>::Apple() {} dans apple.cpp va résoudre ce problème, mais j'utilise des modèles pour éviter d'avoir à écrire tous les constructeurs, etc.

+0

http://stackoverflow.com/search?q=template+header+[c%2B%2B] – wilhelmtell

Répondre

4

Il suffit de mettre vos définitions de fonction de modèle dans vos fichiers d'en-tête. La chose au sujet des fonctions de modèle est, ils ne sont pas réellement des fonctions. Ce sont des modèles de fonctions. Donc, ils ne peuvent pas être compilés hors contexte comme des fonctions normales. Ils ne peuvent être compilés que si les paramètres du template sont connus. Donc la compilation est faite quand le fichier qui les utilise appelle la fonction. Pour que cela se produise, le modèle doit être visible dans le fichier à partir duquel il est appelé, c'est pourquoi vous l'avez mis dans l'en-tête.

+0

Je suis toujours confus qu'il s'agisse de "fonctions de template" ou de "modèles de fonction" :-) – Arun

2

En théorie, sous la norme C++ actuelle, vous pouvez corriger votre code en ajoutant le mot clé export aux modèles.

En réalité, un seul compilateur (Comeau C++) a jamais vraiment supporté export, et c'est un avec une part de marché assez faible. Il y a quelques autres compilateurs basés sur le frontend EDG qui acceptent aussi le code qui contient le mot-clé export, et qui pourraient gérer votre code correctement, mais ne le supportent pas officiellement, donc si ça ne marche pas, vous êtes sur le vôtre (par exemple, Intel C++). Comme il est presque complètement non-implémenté (en grande partie parce qu'il est proche de non-implémentable et semble offrir peu d'avantages réels dans tous les cas) le comité de normalisation C++ a voté pour supprimer export de la prochaine norme. Cela revient à mettre la définition complète de chaque modèle (directement ou indirectement) dans un fichier d'en-tête comme étant la seule façon de faire fonctionner votre code.

+0

+1: Like l'équilibre entre le Standard et la Réalité. – Chubsdad

Questions connexes