我用g ++编译了以下线索
#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
怎么了? 我是c ++的招手
答案 0 :(得分:6)
您正在混淆声明和实例化。声明模板时,不要在其名称后面立即指定类型。相反,声明如下:
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_;}
};
您的原始声明还会混淆string
,const char *
和应该使用T
的通用类型。对于这样的模板,您可能希望让用户定义成员的类型(x_
)。如果您明确声明它为const char *
或string
,则通过限制用户可用于T
的内容而失去通用性。
请注意,我将实例变量的类型,构造函数的参数和data()
的返回类型更改为T
。
当您实际实例化模板类型的变量时,您可以提供具体的类型参数例如:
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
}
每当您在模板声明之外编写模板名称Node
时,在您为参数T
提供值之前,它都不会完整。如果您只是说Node
,编译器将不知道您想要的种节点。
上面有点冗长,所以当你真正使用它时,你也可以使用typedef简化它:
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
}
现在您已经构建了两个节点的链接列表。您可以使用以下内容打印出列表中的所有值:
for (StringNode *n = node; n; n = n->get_next()) {
cout << n->data() << endl;
}
如果一切顺利,这将打印出来:
node
tail
答案 1 :(得分:2)
您的班级声明应如下所示:
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_;}
};
请注意我删除了对string
或const char *
的所有引用,并将其替换为通用类型T
。由于它是模板化的,因此您的类不应引用任何特定类型,而应根据通用T
类型执行所有操作。
稍后在声明const char *
变量时指定Node
。或者它可以是任何其他类型,而不仅仅是const char *
。关键是,当您声明Node
类时,您只需在代码中使用泛型类型T
,而无需引用任何特定类型。只有在实际使用Node
时才指定特定类型。
Node<const char *> stringNode("foo", NULL);
Node<int> intNode(5, NULL);
这使我们能够对Node
类进行单一定义,但能够使用它来创建数据为字符串的节点和数据为整数的节点。万岁模板!