2010-09-19 2 views
0

Я использую Code :: Blocks для создания моего проекта, который содержит три файла: main.cpp, TimeSeries.cpp, TimeSeries.h. TimeSeries.h предоставляет объявления для TimeSeries класса следующим образом:Неопределенная ссылка на ClassName :: ClassName

template<class XType, class YType> class TimeSeries { 
public: 
    TimeSeries(void); 
    ~TimeSeries(void); 
}; 

Тогда TimeSeries.cpp содержит: #include "TimeSeries.h"

template<class XType, class YType> 
TimeSeries<XType, YType>::TimeSeries(void) { 
} 

template<class XType, class YType> 
TimeSeries<XType, YType>::~TimeSeries(void) { 
} 

И, наконец, main.cpp содержит

#include "TimeSeries.h" 
typedef TimeSeries<float, float> FTimeSeries; 

int main(int argc, char** argv) { 
    FTimeSeries input_data; 
    return 0; 
} 

При строительстве с C :: B, я получаю следующую ошибку:

undefined reference to `TimeSeries<float, float>::TimeSeries()' 

Что я могу сделать?

Thanks,
CFP.

ответ

2

Причина разделения кода в заголовках и исходных файлах такова, что объявление и реализация разделены. Компилятор может перевести исходный файл (блок компиляции) в объектный файл, а другие единицы компиляции, которые хотят использовать классы и функции, просто включают заголовочный файл и связывают файл объекта. Таким образом, код должен быть скомпилирован только один раз, и его можно повторно использовать, связав его.

Проблема с шаблонами заключается в том, что, если для них нет параметров, компилятор не может их скомпилировать. Тот же шаблон, созданный с использованием разных параметров, приводит к разным типам. std::vector<int> и std::vector<float>, со стороны компиляторов, никак не связаны. Из-за этого шаблонные классы обычно должны полностью находиться в заголовочном файле, потому что, когда используется шаблон, компилятору необходимо полное определение, чтобы сгенерировать класс в зависимости от параметров.

Как @Gabriel Schreiber указал в his answer, вы можете сообщить компилятору, что он должен скомпилировать шаблон с определенным набором параметров, что сделает его доступным для других единиц компиляции только путем ссылки. Однако это не делает шаблон доступным для других наборов параметров.

+0

Спасибо за ваш исчерпывающий ответ! –

3

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

Каждый файл cpp скомпилирован как отдельный блок, и, таким образом, конструктор и деструктор не скомпилированы. Компилятор не знает, какой тип аргумента шаблона вы будете использовать в main.cpp при компиляции TimeSeries.cpp.

+1

Итак, я бы поместил весь код в файл заголовка? Странно, но так ли? –

+0

@CFP: Может показаться странным, но для шаблонов это (к сожалению) путь. –

1

Вы должны добавить это в .cpp-файл (ниже определений):

template class TimeSeries<float, float>; 

Когда компилятор компилирует TimeSeries.cpp он не знает, какие для каких типов шаблон необходимо потому, что он используется в другом исходном файле. Вы должны явно указать компилятору.

Читайте о Явного шаблона Создание в вашей копии Страуструп или в Интернете.

+0

Я вижу, спасибо =) Но это убивает большую часть возможностей шаблонов, не так ли? –

Смежные вопросы