Б-же, как меня з%?%"а эта проблема, убил на нее 2.5 часа, ни один преподаватель в вузе не сказал про эту проблему. Чувствую butthurt. Надеюсь, теперь вы не совершите такую же ошибку...
Предположим, что у нас есть класс (ОН находится в .h файле)
Предположим, что у нас есть класс (ОН находится в .h файле)
template < typename T>
class Single_Linked_List
{
private:
Node *head;
Node *tail;
Node *current;
unsigned size;
public:
void Push_Front(const T& element);
void Push_Back(const T& element);
T Pop_Front();
T Pop_Back();
////и дохрена методов внизу с конструктором деструктором
};
У нас есть .cpp файл, где находится описание всех методов итд:
#include "Single_Linked_List.h"
////
описание всех методов
Теперь мы попробуем потестить наш класс односвязного списка:
Single_Linked_List<int> sll;
sll.Push_Front(1);
sll.Push_Front(1);
ОШИБКА -_-, в чем проблема ?
error LNK2019: unresolved external symbol "public: __thiscall Single_Linked_List
Видно, что компилятор ПРОСТО не видит .cpp файл. Теперь, подключим в main.cpp вместо .h файла, .cpp файл. О, ЧУДО, оно работает БЛ%^#АТЬ.
Давайте еще подробнее разберемся что к чему:
Заголовочный файл (header - .h) - файл, где находится описание, но не реализация.
.cpp - файл, где находится реализация. На самом деле они ничем не отличаются, разделение на .h и .cpp файлы - это просто формальность, для того, чтобы отличить, где реализация, а где описание. При компиляции, компилятор включает все include файлы в единую единицу трансляции и делают из него .obj файл. Потом из всех .obj файлов собирается программа. Если в .obj файле есть 1 реализация функции func, то она будет видна и в других .obj файлах, НО, если реализаций много, то будет ошибка линковщика.
В нашем случае реализацию шаблонной функции можно инстанцировать (генерирование типов и функций) множеством способов (func<int>, func<float>, func<double>...) поэтому будет ошибка.
- Подключать в main.cpp не .h файла, а его реализацию .cpp файл.
- Всю реализацию хранить вместе с описанием (.h или .hpp файлы)
- Подключить в конце .h файла .cpp файл.
- Использовать export template (не поддерживается многими компиляторами, в том числе VS2010, поэтому я не смогу его продемонстрировать, он реализован только в Comeau)
- Просто написать объявление всех вариантов использования списка в cpp файле, например: template class Single_Linked_List<int>; потом с float и т. д.
- Использовать глобальную функцию, где опробовать все используемые методы в main'е, например (сделать только объявление глобальной функции в .h и все):
void TemporaryFunction ()
{
Single_Linked_List sll;
sll.Push_Front(0);
sll.Display();
}
После того, как в .h файле мы сделали такую функцию, теперь в main.cpp работают:
конструктор, деструктор, Push_Front, Display. С другими методами будет ошибка.
конструктор, деструктор, Push_Front, Display. С другими методами будет ошибка.
0 коммент.:
Отправить комментарий