Вы смешиваете объявления и экземпляры. Когда вы объявляете шаблон, вы не указываете тип сразу после его имени. Вместо этого объявите это так:
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