2009-06-26 6 views
2

Je compila les cordons suivants avec g ++Je ne peux pas compiler en utilisant le modèle en C++

#include <iostream> 
#include <string> 
using namespace std; 
template<class T> 
class Node<const char*>{ 
private: 
    string x_; 
    Node* next_; 
public: 
    Node (const char* k, Node* next):next_(next),x_(k){} 
    string data(){return x_;} 
    Node *get_next(){return next_;} 
}; 

$ g++ -c node01.cc 
node01.cc:5: error: ‘Node’ is not a template 

Qu'est-ce qui ne va pas? Je suis Begginer pour C++

Répondre

6

Vous mélangez des déclarations et des instanciations. Lorsque vous déclarez un modèle, vous ne spécifiez pas un type immédiatement après son nom. Au lieu de cela, déclarer comme ceci:

template<class T> 
class Node { 
private: 
    const T x_; 
    Node *next_; 
public: 
    Node (const T& k, Node *next) : x_(k), next_(next) { } 
    const T& data(){return x_;} 
    Node *get_next(){return next_;} 
}; 

Votre déclaration d'origine embrouille aussi string, const char * et types génériques qui devraient être en termes de T. Pour un modèle comme celui-ci, vous voulez probablement laisser l'utilisateur définir le type du membre (x_). Si vous le déclarez explicitement comme const char * ou string, vous perdez la généricité en limitant ce que l'utilisateur peut utiliser pour T.

Notez que j'ai changé les types des variables d'instance, les paramètres du constructeur et le type de retour de data() pour être aussi en termes de T.

Lorsque vous instanciez réellement une variable du type de modèle, vous pouvez fournir un paramètre de type concret, par exemple.:

int main(int argc, const char **argv) { 
    Node<char*> *tail = new Node<char*>("tail", NULL); 
    Node<char*> *node = new Node<char*>("node", tail); 
    // do stuff to mynode and mytail 
} 

Chaque fois que vous écrivez le nom du modèle Node en dehors de la déclaration de modèle, il est complet jusqu'à ce que vous fournissez une valeur pour le paramètre T. Si vous venez de dire Node, le compilateur ne saura pas quel genre du nœud que vous vouliez.

Ce qui précède est un peu bavard, donc vous pouvez aussi simplifier avec un typedef lorsque vous utilisez réellement:

typedef Node<char*> StringNode; 
int main(int argc, const char **argv) { 
    StringNode *tail = new StringNode("tail", NULL); 
    StringNode *node = new StringNode("node", tail); 
    // do stuff to mynode and mytail 
} 

Maintenant que vous avez construit une liste chaînée de deux nœuds. Vous pouvez imprimer toutes les valeurs de la liste avec quelque chose comme ceci: Si tout va bien

for (StringNode *n = node; n; n = n->get_next()) { 
    cout << n->data() << endl; 
} 

, ceci affichera:

node 
tail 
2

Votre déclaration de classe devrait ressembler à ceci:

template<class T> 
class Node{ 
private: 
    T x_; 
    Node* next_; 
public: 
    Node (const T& k, Node* next):next_(next),x_(k){} 
    T data(){return x_;} 
    Node *get_next(){return next_;} 
}; 

Notez comment j'ai supprimé toutes les références à string ou const char * et les a remplacés par le type générique T. Votre classe, puisqu'elle est basée sur des modèles, ne devrait pas faire référence à un type spécifique mais devrait tout faire en termes de type générique T. Le const char * est spécifié plus tard lorsque vous déclarez une variable Node. Ou il pourrait être n'importe quel autre type, pas seulement const char *. Le fait est que lorsque vous déclarez la classe Node, vous utilisez simplement le type générique T dans le code sans référence à un type spécifique. Vous spécifiez un type spécifique uniquement lorsque vous utilisez réellement un Node.

Node<const char *> stringNode("foo", NULL); 
Node<int>   intNode(5, NULL); 

Cela nous a permis d'avoir une définition unique de la classe Node, mais être en mesure de l'utiliser pour créer les nœuds où les données sont une chaîne et les noeuds où les données est un entier. Hourra templating!

Questions connexes