Когда я пишу код С++ для класса с использованием шаблонов и разделяю код между исходным (CPP) файлом и файлом заголовка (H), я получаю много ошибок "неразрешенных внешних символов", когда дело доходит до ссылки на окончательный исполняемый файл, несмотря на то, что объектный файл правильно построен и включен в ссылку. Что происходит здесь, и как я могу это исправить?
Почему при использовании шаблонов я получаю ошибки "неразрешенных внешних символов"?
Ответ 1
Шаблонные классы и функции не создаются, пока они не используются, как правило, в отдельном файле .cpp(например, в источнике программы). Когда шаблон используется, компилятору нужен полный код для этой функции, чтобы иметь возможность создавать правильную функцию с соответствующим типом. Однако в этом случае код для этой функции подробно описан в исходном файле шаблона и, следовательно, недоступен.
В результате всего этого компилятор просто предполагает, что он определен в другом месте и только вставляет вызов функции templated. Когда дело доходит до компиляции исходного файла шаблона, тип конкретного шаблона, который используется в исходном коде программы, не используется там, поэтому он все равно не будет генерировать код, необходимый для этой функции. Это приводит к неразрешенному внешнему символу.
Доступны следующие решения:
- включить полное определение функция-член в файл заголовка шаблона и не иметь исходный файл для шаблона,
- определить все функции-члены в исходный файл шаблона как "inline", или
-
определить участника функции в источнике шаблона с ключевым словом "экспорт". К сожалению, это не поддерживается много компиляторов.(Обновление: это было удалено из стандартного как С++ 11.)
Оба 1 и 2 в основном решают проблему, предоставляя компилятору доступ ко всему коду для шаблонной функции, когда он пытается построить типизированную функцию в исходном коде программы.
Ответ 2
Другой вариант - поместить код в файл cpp и в тот же файл cpp добавить явные экземпляры шаблона с типами, которые вы ожидаете использовать. Это полезно, если вы знаете, что собираетесь использовать его только для нескольких типов, которые вы знаете заранее.
Ответ 3
Для каждого файла, который содержит файл .h, вы должны вставлять обе строки:
#include "MyfileWithTemplatesDeclaration.h"
#include "MyfileWithTemplatesDefinition.cpp"
Пример
#include "list.h"
#include "list.cpp" //<---for to fix bug link err 2019
int main(int argc, _TCHAR* argv[])
{
list<int> my_list;
my_list.add_end(3);
.
.
}
Кроме того, вы не забудете разместить свой класс объявлений среди констант в сантинеле
#ifndef LIST_H
#define LIST_H
#include <iostream>
.
.
template <class T>
class list
{
private:
int m_size,
m_count_nodes;
T m_line;
node<T> *m_head;
public:
list(void);
~list(void);
void add_end(T);
void print();
};
#endif