Разделение класса шаблона на несколько файлов приводит к проблемам с ссылками - PullRequest
2 голосов
/ 25 октября 2010

Я создал пример ниже, чтобы проиллюстрировать мою проблему.По сути, когда я разделяю класс шаблона на отдельный файл .h / .cpp, я получаю неразрешенные символы для конструктора.Используя один файл, он прекрасно компилируется.Что вызывает это?

fruits.cpp:

#include "apple.h"

class FruitsDB {
    public:
        void addApple();
};

void FruitsDB::addApple() {
    Apple<int> m;
}

int main() {
    FruitsDB fruits;
    return 0;
}

apple.h:

template <typename T>
class Apple {
    public:
        Apple();
        ~Apple();
};

apple.cpp

template <typename T>
Apple<T>::Apple() {
}

template <typename T>
Apple<T>::~Apple() {
}

Thisвыдает ошибку компилятора:

g++    -c -o fruits.o fruits.cpp
g++    -c -o apple.o apple.cpp
g++ -Wall -ggdb fruits.o apple.o -o fruits
Undefined symbols:
  "Apple<int>::Apple()", referenced from:
      FruitsDB::addApple()     in fruits.o
  "Apple<int>::~Apple()", referenced from:
      FruitsDB::addApple()     in fruits.o
ld: symbol(s) not found

Я думал, что это был мой код, вызывающий проблему, но объединение файлов не создает проблему.Я предполагаю, что мне нужно включить файл где-то, где я не.Я полностью потерян.

Примечание: добавление template <> Apple<int>::Apple() {} в apple.cpp решит эту проблему, но я использую шаблоны, чтобы избежать необходимости писать все эти конструкторы и т. Д.

Ответы [ 2 ]

4 голосов
/ 25 октября 2010

Просто поместите определения функций вашего шаблона в заголовочные файлы. Что касается шаблонных функций, то они на самом деле не являются функциями. Это шаблоны функций. Поэтому они не могут быть скомпилированы вне контекста, как обычные функции. Они могут быть скомпилированы, только если известны параметры шаблона. Таким образом, компиляция выполняется, когда файл, который их использует, вызывает функцию. Чтобы это произошло, шаблон должен быть видимым для файла, из которого он вызывается, поэтому вы помещаете его в заголовок.

2 голосов
/ 25 октября 2010

Теоретически, согласно действующему стандарту C ++, вы можете исправить свой код, добавив ключевое слово export в шаблоны.

На самом деле, только один компилятор (Comeau C ++) когда-либо действительно поддерживал export, и это один с довольно небольшой долей рынка. Существует несколько других компиляторов, основанных на интерфейсе EDG, которые также принимают код, содержащий ключевое слово export, и могут корректно обрабатывать ваш код, но официально не поддерживают его, поэтому, если он не работает, вы ' самостоятельно (например, Intel C ++). Поскольку он практически полностью не реализован (в основном потому, что он практически не реализуем и, по-видимому, в любом случае дает мало реальных преимуществ), комитет по стандартизации C ++ проголосовал за исключение export из следующего стандарта.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...