Класс С++ с шаблоном не может найти его конструктор

У меня проблема, которую я действительно не понимаю. У меня есть класс 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: плохой ответ, возможно, это не так.