Я не могу скомпилировать, используя шаблон в C ++ - PullRequest
2 голосов
/ 26 июня 2009

Я скомпилировал следующие шнуры с 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 ++

Ответы [ 2 ]

6 голосов
/ 26 июня 2009

Вы смешиваете объявления и экземпляры. Когда вы объявляете шаблон, вы не указываете тип сразу после его имени. Вместо этого объявите это так:

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
2 голосов
/ 26 июня 2009

Ваше объявление класса должно выглядеть так:

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, но иметь возможность использовать его для создания как узлов, где данные являются строкой, так и узлов, где данные являются целыми числами. Ура шаблонизатор!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...