Класс С++ с шаблоном не может найти его конструктор
У меня проблема, которую я действительно не понимаю. У меня есть класс 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: Undefined символы:
node <INT> :: node (целое)
странная часть... если я переведу конструктор из .cpp в файл .h, все будет хорошо. Где проблема?
Ответы
Ответ 1
Проблема заключается в том, что шаблоны не являются классами - вы обычно не записываете их в два отдельных файла. Классы шаблонов - это код, который компилятор использует для генерации классов. Таким образом, ваш код реализации должен быть эффективно встроен, т.е. В заголовок, как вы обнаружили.
Для более полного объяснения того, почему это должно быть так, см. С++ FAQ Lite.
Ответ 2
Как правило, вы должны поместить все члены шаблона внутри файла заголовка. Шаблоны скомпилированы на основе использования, и, следовательно, все определение должно быть доступно везде, где они используются. Ввод кода в файл заголовка решит эту проблему.
Единственный раз, когда вы можете поместить определение шаблона в файл CPP, - это когда шаблон будет использоваться только в этом CPP файле. Причина в том, что он соответствует стандарту, что все определение доступно для компиляции.
Перемещение содержимого node.cpp на node.h устранит проблему.
Странные сценарии
Затем вы также можете поместить все в файл CPP и включить файл CPP. Таким образом, С++ является гибким. Я только упоминаю об этом, потому что я видел это раньше. Я на самом деле ушиб челюсть, когда он попал в верхнюю часть моего стола.
Ответ 3
Когда вы используете node<int>
, вы, скорее всего, не включили node.cpp. Поэтому компилятор не может создать экземпляр конструктора node<int>::node<int>
. Обычно вы помещаете весь код шаблона, включая все реализации методов, в файл заголовка или что-то, что включено в него.
Ответ 4
Общепринятая практика заключается в том, чтобы поместить всю реализацию в файл .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);
}
Ответ 5
// 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>;
Ответ 6
Если нет вызова функции, компилятор не выдаст никакого кода, и компоновщик его не найдет.
Вы должны поместить функцию в заголовок, где она принадлежит.
Ответ 7
неявное создание экземпляра отключено, вам нужно
template class node<int>;
где-нибудь в вашем коде (node.cpp возможно)
EDIT: плохой ответ, возможно, это не так.