Разделение шаблонных классов C ++ на файлы .hpp / .cpp - возможно ли это? - PullRequest
85 голосов
/ 12 ноября 2009

Я получаю ошибки при попытке скомпилировать шаблонный класс C ++, который разбит на файлы .hpp и .cpp:

$ g++ -c -o main.o main.cpp  
$ g++ -c -o stack.o stack.cpp   
$ g++ -o main main.o stack.o  
main.o: In function `main':  
main.cpp:(.text+0xe): undefined reference to 'stack<int>::stack()'  
main.cpp:(.text+0x1c): undefined reference to 'stack<int>::~stack()'  
collect2: ld returned 1 exit status  
make: *** [program] Error 1  

Вот мой код:

stack.hpp

#ifndef _STACK_HPP
#define _STACK_HPP

template <typename Type>
class stack {
    public:
            stack();
            ~stack();
};
#endif

stack.cpp

#include <iostream>
#include "stack.hpp"

template <typename Type> stack<Type>::stack() {
        std::cerr << "Hello, stack " << this << "!" << std::endl;
}

template <typename Type> stack<Type>::~stack() {
        std::cerr << "Goodbye, stack " << this << "." << std::endl;
}

main.cpp

#include "stack.hpp"

int main() {
    stack<int> s;

    return 0;
}

ld, конечно, правильно: символы не в stack.o.

Ответ на на этот вопрос не помогает, как я уже делаю, как говорится.
Этот может помочь, но я не хочу переносить каждый метод в файл .hpp - мне не нужно, не так ли?

Является ли единственно разумным решением переместить все в файле .cpp в файл .hpp и просто включить все, а не ссылаться в качестве отдельного объектного файла? Это кажется ужасно ужасно! В этом случае я мог бы также вернуться к своему предыдущему состоянию и переименовать stack.cpp в stack.hpp и покончить с этим.

Ответы [ 15 ]

0 голосов
/ 27 апреля 2014

1) Помните, что основная причина разделения файлов .h и .cpp состоит в том, чтобы скрыть реализацию класса как отдельно скомпилированный код Obj, который можно связать с кодом пользователя, который включает .h класса.

2) Не шаблонные классы имеют все переменные, которые конкретно и конкретно определены в файлах .h и .cpp. Таким образом, компилятор будет располагать необходимой информацией обо всех типах данных, используемых в классе, перед компиляцией / трансляцией, генерацией объекта / машинного кода. Шаблонные классы не имеют информации о конкретном типе данных до того, как пользователь класса создаст экземпляр объекта, передавая требуемый тип данных:

        TClass<int> myObj;

3) Только после этого создания компилятор генерирует конкретную версию класса шаблона, соответствующую переданным типам данных.

4) Следовательно, .cpp НЕ может быть скомпилирован отдельно, не зная специфический тип данных пользователя. Таким образом, он должен оставаться в качестве исходного кода внутри «.h», пока пользователь не укажет требуемый тип данных, затем он может быть сгенерирован для определенного типа данных, а затем скомпилирован

0 голосов
/ 26 июня 2013

Я работаю с Visual Studio 2010, если вы хотите разделить ваши файлы на .h и .cpp, включите заголовок cpp в конец файла .h

0 голосов
/ 12 ноября 2009

Ключевое слово "export" - это способ отделить реализацию шаблона от объявления шаблона. Это было введено в стандарте C ++ без существующей реализации. Со временем только пара компиляторов фактически осуществили это. Подробную информацию читайте на Информировать ИТ-статью об экспорте

0 голосов
/ 12 ноября 2009

Другая возможность - сделать что-то вроде:

#ifndef _STACK_HPP
#define _STACK_HPP

template <typename Type>
class stack {
    public:
            stack();
            ~stack();
};

#include "stack.cpp"  // Note the include.  The inclusion
                      // of stack.h in stack.cpp must be 
                      // removed to avoid a circular include.

#endif

Мне не нравится это предложение как вопрос стиля, но оно может вас устроить.

0 голосов
/ 12 ноября 2009

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

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