Почему объявление / определение должны быть оба в исходном файле для шаблона класса в C ++? - PullRequest
4 голосов
/ 15 октября 2010

Кто-нибудь может уточнить причину?

Ответы [ 3 ]

3 голосов
/ 15 октября 2010

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

Обещанный пример:

template<class T>
void swap(T & a, T & b)
{
    T temp = a;
    a = b;
    b = temp;
}

Единственные требования к классу T здесь заключаются в том, что он имеет открытый оператор присваивания (=). Это почти каждый класс, который когда-либо был реализован или задуман. Однако каждый класс реализует оператор присваивания по-своему. Один и тот же машинный код не может быть сгенерирован для swap , swap и swap . Каждая из этих функций должна быть уникальной. В то же время компилятор не может предвидеть все множество различных типов, которые вы можете передать этой функции, поэтому он не может генерировать функции заранее. Поэтому он должен ждать, пока функция не будет вызвана, а затем он может быть скомпилирован.

Например, допустим, у меня есть функция, определенная выше, в "swap.h". Затем в "main.cpp" я делаю это:

int main()
{
    int a=5, b=10;
    double c=3.5, d=7.9;
    string s1="hello";
    string s2="world";

    swap(a,b);
    swap(c,d);
    swap(s1,s2);
}

В этом примере были созданы 3 разные функции. Один, чтобы поменять местами, один, чтобы обменять двойники, и один, чтобы поменять местами строки. Чтобы создать эти функции, компилятор должен был видеть код шаблона. Если бы он находился в отдельном исходном файле, например, «swap.cpp», компилятор не смог бы его увидеть, потому что, как я уже говорил, каждый исходный файл компилируется независимо друг от друга.

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

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

  1. (Trivial) Шаблон используется только в одном исходном файле, поэтому тело может находиться в том же исходном файле.
  2. Сделать тело доступным при каждом использовании, что часто означает в заголовочном файле.
  3. В исходном файле, который содержит тело, явно создайте экземпляр каждой необходимой комбинации параметров шаблона.
1 голос
/ 15 октября 2010

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

На самом деле, я считаю это плохой вещью, но это вполне понятно, учитывая, что их довольно сложно использовать отдельно (но это можно сделать!).

РЕДАКТИРОВАТЬ

Предположим, у вас есть

  • myTemplateClass.h, который объявляет шаблонный класс MyTemplateClass
  • myTemplateClass.hpp, который определяет его членов класса (включая myTemplateClass.h)
  • использование MyTemplateClass внутри main.cpp

Просто включите myTemplateClass.h в main.cpp и создайте myTemplateClassInt.cpp следующим образом:

#include "myTemplateClass.hpp"

template MyTemplateClass<int>;

Делая это, вы указываете компилятору создавать экземпляры всех методов-шаблонов MyTemplateClass для параметра шаблона «int».Так как у него есть доступ к myTemplateClass.hpp, такие методы будут сгенерированы безупречно ... И компоновщик не будет жаловаться.

Конечно, этот подход требует, чтобы вы использовали какое-то место, где создаются экземпляры классов вашего шаблонаопределены.

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