Вы получаете ошибки компоновки, а не ошибки компилятора. Это говорит нам о том, что компилятор знал, что это за функция Tree::add()
, но не имел определения. В Tree.h я вижу объявление функции add (), но не определение. Это выглядит странно для меня; Кто-нибудь знает, откуда появился Tree.h?
Обычно шаблонный класс поставляется с определениями функций-членов во включаемом файле, так как функции должны быть где-то созданы, и самое простое для компилятора - создать экземпляр при использовании и позволить компоновщику разобраться. Если бы определения были в Tree.h, я бы ожидал, что все будет работать как запланировано.
Итак, я собираюсь выйти на конечность и предположить, что определения находятся в отдельном файле, не связаны в нем, и что в других местах есть положения для создания экземпляров для базовых типов, таких как Tree<int>
. Это, по-видимому, упрощает компиляцию, так как обычно эти вещи компилируются в нескольких местах, и это требует времени.
В этом случае вам нужно найти, где создается экземпляр Tree<int>
, и добавить экземпляр для вашего класса.
Я мог бы быть далеко от базы, но мое объяснение соответствует фактам, которые вы дали.
Редактировать после первых комментариев :
Шаблоны несколько сложнее, чем обычные функции, что обычно не является реальной проблемой. Если бы определения всех вызовов были в Tree.h, то Festival.cpp мог бы создать экземпляр Tree<Band>
, и все было бы круто. Это обычная техника, и вы столкнулись с этой проблемой, потому что вы ее не используете.
Когда вы пишете функцию, она компилируется, и компоновщик найдет ее. Любая подпрограмма, вызывающая эту функцию, должна знать прототип функции, поэтому она будет знать, как ее вызвать. Когда вы пишете шаблон, вы не пишете ничего, что попадет непосредственно в программу, но любое использование шаблона считается записью всех функций.
Следовательно, где-то в вашей программе должно быть какое-то использование Tree<Band>
, чтобы была скомпилирована функция Tree<Band>::add()
. Определение Tree<T>::add
должно быть доступно для компилятора, когда создается экземпляр Tree<Band>
, потому что в противном случае компилятор не имеет представления, что компилировать. В этом случае он генерирует вызов функции, будучи уверенным, что вы убедитесь, что функция скомпилирована в другом месте.
Следовательно, вам нужно создать экземпляр Tree<Band>
внутри файла, который имеет доступ к обоим определениям Tree<T>
и Band
. Это, вероятно, означает, что файл, который включает или включает Tree.cpp и включает Festival.h.
Компоновщик уже использует Tree.cpp, но в Tree.cpp не определено Tree<Band>
, поэтому для компоновщика это бессмысленно. Шаблоны полезны только для компилятора, а компоновщик работает только с тем, что компилятор сгенерировал из шаблонов.
Самый быстрый способ решить эту проблему - взять определения из Tree.cpp и поместить их в Tree.h. К сожалению, это может увеличить время компиляции и ссылки. Другой метод заключается в создании экземпляров всех шаблонов, используемых в Tree.cpp, чтобы они были скомпилированы там.