Класс C ++ с шаблоном не может найти своего конструктора - PullRequest
15 голосов
/ 13 марта 2009

У меня есть проблема, которую я не понимаю. У меня есть класс Node.

template<class T>
class node {
protected:
    T _data;
public:
    node(T data);   
};

Это в файле "node.h". В файле "node.cpp" есть этот конструктор:

#include "node.h"

template<class T>
node<T>::node (T data) {
    _data = data;
}

Пока компилятор не находит ошибки, компоновщик (ld) сообщает мне:

/ usr / bin / ld: неопределенные символы:

узел :: узел (INT)

странная часть ... если я перенесу конструктор из .cpp в файл .h, все будет работать нормально. Где проблема?

Ответы [ 7 ]

23 голосов
/ 13 марта 2009

Проблема в том, что шаблоны не являются классами - обычно вы не пишете их в двух отдельных файлах. Шаблонные классы - это код, который компилятор использует для генерации классов. Таким образом, ваш код реализации должен эффективно быть встроенным, т. Е. В заголовке, как вы обнаружили.

Более полное объяснение почему так и должно быть, см. C ++ FAQ Lite .

13 голосов
/ 13 марта 2009

Как правило, вы должны поместить все элементы шаблона в заголовочный файл. Шаблоны компилируются по мере использования, и, следовательно, все определение должно быть доступно везде, где они используются. Размещение кода в заголовочном файле решит эту проблему.

Единственный раз, когда вы можете поместить определение шаблона в файл CPP, это когда шаблон будет использоваться только внутри этого файла CPP. Причина в том, что он соответствует стандарту, что все определение доступно для компиляции.

Перемещение содержимого node.cpp в node.h решит проблему.

Странные сценарии

Опять же, вы также можете поместить все в файл CPP и включить файл CPP. C ++ гибок в этом смысле. Я упоминаю об этом только потому, что видел в прошлом. Я на самом деле ушиб мою челюсть, когда она ударилась о верхнюю часть моего стола.

1 голос
/ 20 августа 2012
// You can put templates declaration in header and definition in source  
// node.h or wherever you include file gets included
extern template class node<int>;

// node.cpp or where ever source file you want to use it
// But use it only once for each type of generated class
template class node<int>;
1 голос
/ 13 марта 2009

Общепринятой практикой является помещение всей реализации в файл .h, чтобы классы могли быть сгенерированы из шаблона при необходимости.

Если вы заранее знаете, с какими типами будет создаваться экземпляр вашего шаблона, вы можете немного обмануть. Просто убедитесь, что ваш .cpp содержит сценарий использования для каждого типа и метода, который вам понадобится. Важно, чтобы вариант использования шел после кода шаблона. Например. для "node.cpp" используйте

#include "node.h"

template<class T>
node<T>::node (T data) {
    _data = data;
}

void dummy(void)
{
    node<int> intnode(0);
    node<double> doublenode(0.0);
}
1 голос
/ 13 марта 2009

Когда вы используете node<int>, вы, скорее всего, не включили node.cpp. Поэтому компилятор не может создать экземпляр конструктора node<int>::node<int>. Обычно вы помещаете весь код шаблона, включая все реализации методов, в заголовочный файл или что-то включенное в него.

0 голосов
/ 13 марта 2009

неявная реализация отключена, вам нужно

template class node<int>;

где-то в вашем коде (возможно, node.cpp)

РЕДАКТИРОВАТЬ: плохой ответ, вероятно, это не так.

0 голосов
/ 13 марта 2009

Если нет вызова функции, компилятор не выведет никакого кода, а компоновщик не найдет его.

Вы должны поместить функцию в заголовок, где она принадлежит.

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