Ошибка шаблонов C ++ - PullRequest
       12

Ошибка шаблонов C ++

2 голосов
/ 20 сентября 2009

Я пытаюсь написать простой векторный класс с шаблонами, но когда я разделяю его на файлы .h и .cpp, я получаю следующие ошибки:

неопределенная ссылка на vector<int>::vector()' undefined reference to vector :: add (int) ' неопределенная ссылка на vector<int>::add(int)' undefined reference to vector :: remove (int) '

код: http://pastie.org/623584

Ответы [ 4 ]

3 голосов
/ 20 сентября 2009

Либо следуйте совету Навина и держите его в заголовке, либо добавьте

template class vector<int>;

К вашему .cc файлу. Но тогда вам нужно будет создать его экземпляр для всех возможных аргументов шаблона.

1 голос
/ 20 сентября 2009

Причина вашей проблемы заключается в организации файлов в C ++.

О заголовках и источниках

Источники - это файлы, которые скомпилированы в двоичные «объектные файлы», а затем соединены вместе для создания окончательного двоичного файла (либо библиотеки, либо исполняемого файла).

Но чтобы один источник использовал код, определенный в другом источнике, они должны совместно использовать «объявления» кода. Таким образом, объявление должно быть размещено в общих файлах, которые мы будем называть заголовочными файлами.

Обычно код в заголовках не является «истинным кодом», а только декларацией о существовании этого истинного кода.

Это то, что вы сделали со своим пользовательским вектором: поместите объявление в заголовок, а реализацию в исходный, и включите заголовок в основной.

О вкладывании

Теперь некоторый «истинный код» может быть помещен в заголовки, обычно путем добавления к нему ключевого слова «inline».

Опять же, это не совсем верный код: компилятор и компоновщик выяснят, что с ним делать, но он может либо:

  • Переместить код функции в «объектный файл» и связать там все остальные «объектные файлы»
  • Встроенный код, в котором используется встроенная функция
  • Два вышеуказанных решения одновременно

Но встроенная функция вполне может исчезнуть из двоичного файла, если она не используется.

О шаблонах

Шаблоны чем-то похожи на объявление: это не "истинный код", а "потенциальный код". Это даже более «потенциал», чем встроенный код, потому что код шаблона должен быть создан для правильных параметров шаблона.

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

Существуют и другие способы работы с шаблонами, но так будет всегда.

Последний совет

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

* * Пример 1 042:

файл: MyObject.hpp

#include <MyObject_header.hpp>
#include <MyObject_source.hpp>

файл: MyObject_header.hpp

class MyObject
{
   // Etc.
} ;

файл: MyObject_source.hpp

#include <MyObject_header.hpp>

MyObject::MyObject()
{
   // etc.
}

// etc.
0 голосов
/ 20 сентября 2009

Есть несколько способов избежать таких проблем с линковкой, это должно быть очень интересно для вас. читать http://www.parashift.com/c%2B%2B-faq-lite/templates.html#faq-35.15

Это объясняет вам различные решения. Если вы не создаете экземпляр шаблона, вы должны поместите определения и реализации в ваш .h , но если вам нужно, вы должны добавить что-то вроде

template class vector<int>;

или (и)

template class vector<double>;

в вашем .cpp , в соответствии с шаблонами, которые вы создаете.

0 голосов
/ 20 сентября 2009

Вы не можете разделить объявление и реализацию класса шаблона на .h & .cpp. Он должен быть там в самом .h. Когда vector в main (), компилятор пытается создать экземпляр класса vector. Для этого ему необходимо знать полную реализацию класса, поэтому вам нужно написать весь шаблонный класс в самом .h.

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