Почему при использовании шаблонов возникают ошибки "неразрешенный внешний символ"?
Когда я пишу код C++ для класса с использованием шаблонов и разделяю код между исходным (CPP) файлом и файлом заголовка (H), я получаю массу ошибок "неразрешенный внешний символ", когда речь идет о связывании конечного исполняемого файла, несмотря на то, что объектный файл был правильно построен и включен в ссылки. Что здесь происходит, и как я могу это исправить?
3 ответа
Шаблонные классы и функции не создаются, пока они не используются, как правило, в отдельном файле.cpp (например, исходный код программы). Когда шаблон используется, компилятору необходим полный код этой функции, чтобы иметь возможность построить правильную функцию с соответствующим типом. Однако в этом случае код этой функции подробно описан в исходном файле шаблона и, следовательно, недоступен.
В результате всего этого компилятор предполагает, что он определен в другом месте, и вставляет только вызов шаблонной функции. Когда дело доходит до компиляции исходного файла шаблона, конкретный тип шаблона, который используется в исходном коде программы, там не используется, поэтому он все равно не будет генерировать код, необходимый для функции. Это приводит к неразрешенному внешнему символу.
Для этого доступны следующие решения:
- включить полное определение функции-члена в заголовочный файл шаблона и не иметь исходного файла для шаблона,
- определить все функции-члены в исходном файле шаблона как "встроенные", или
-
определить функции-члены в источнике шаблона с ключевым словом "export".К сожалению, это не поддерживается многими компиляторами.(Обновление: это было удалено из стандарта с C++ 11.)
И 1, и 2 в основном решают проблему, предоставляя компилятору доступ к полному коду для шаблонной функции, когда он пытается создать типизированную функцию в исходном коде программы.
Другой вариант - поместить код в файл cpp и в тот же файл cpp добавить явные экземпляры шаблона с типами, которые вы ожидаете использовать. Это полезно, если вы знаете, что собираетесь использовать его только для пары типов, которые вы знаете заранее.
Для каждого файла, включающего файл.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