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

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

Решение

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

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

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

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

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

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

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

Неявная инстанциация отключена, нужно

template class node<int>;

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

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

// 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>;

Общепринятая практика - поместить всю реализацию в файл.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);
}

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

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

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

Другие вопросы по тегам