Pourquoi l'implémentation et la déclaration d'une classe de modèle devraient-elles être dans le même fichier d'en-tête? L'un d'entre vous pourrait-il l'expliquer par l'exemple?
Réponses
Trop de publicités?Le compilateur a besoin d'avoir accès à l'ensemble de définition de modèle (et pas seulement de la signature) afin de générer du code pour chaque instanciation du modèle, de sorte que vous devez déplacer les définitions des fonctions de votre en-tête.
Pour plus de détails, lisez au sujet de L'Inclusion du Modèle.
La définition d'un modèle de classe et de la mise en œuvre de ses fonctions de membre doit être visible à chaque lieu qui instancie avec un type distinct. c'est à dire pour pouvoir instancier myTemplate<int>
vous avez besoin de voir l'intégralité de la définition et de la mise en œuvre de l' myTemplate
.
La meilleure façon de le faire est de mettre la définition du modèle et de ses fonctions de membre dans le même en-tête, mais il y a d'autres façons. Par exemple, vous pouvez mettre le membre implémentations de fonction dans un fichier séparé qui a été inclus séparément. Vous pouvez ensuite inclure à partir de la première en-tête, ou seulement inclure la mise en œuvre de fichier là où vous en avez besoin.
Par exemple, une pratique consiste à instancier explicitement un modèle pour l'ensemble particulier de paramètres dans un .fichier cpp et déclarer ces instanciations extern
dans l'en-tête. De cette façon, ces instanciations peut être utilisé dans d'autres fichiers source sans nécessiter la mise en œuvre du modèle des fonctions de membre pour être visible. Toutefois, sauf si vous incluez le fichier d'implémentation, vous ne serez pas en mesure d'utiliser d'autres ensembles de paramètres du modèle.
c'est à dire si vous avez myTemplate<int>
et myTemplate<std::string>
défini comme extern
ensuite vous pouvez les utiliser très bien, mais si myTemplate<double>
n'est pas définie en extern
alors vous ne pouvez pas l'utiliser sans la mise en œuvre.
Dans le cas d'une classe normale, la déclaration est juste suffisante pour la compilation et les définitions correspondantes seront liées .
Dans le cas des modèles, le compilateur a également besoin de la définition pour générer le code.
La différence est mieux expliquée dans la FAQ C ++ .
Ils n'ont pas à.
Ce qui est nécessaire pour la définition de modèle afin d'être visible au moment de l'instanciation (où il est utilisé) pour que le compilateur puisse dériver de la classe de fonction à partir du modèle à ce point.
Cependant, il est très courant d'utiliser deux fichiers d'en-tête pour les classes de modèle:
// foo_fwd.hpp
template <typename T, typename U> struct Foo;
// foo.hpp
#include "foo_fwd.hpp"
template <typename T, typename U> struct Foo { typedef std::pair<T,U> type; };
Cela permet à ceux qui n'ont pas besoin de la pleine définition de modèle pour inclure un peu plus légère en-tête, par exemple:
//is_foo.hpp
#include <boost/mpl/bool.hpp>
#include "foo_fwd.hpp"
template <typename Z>
struct is_foo: boost::mpl::false_ {};
template <typename T, typename U>
struct is_foo< Foo<T,U> >: boost::mpl::true_ {};
ce qui peut accélérer la compilation en temps un peu.