Короче говоря, вам нужно иметь все тело ( определение ) функции шаблона, видимой для модуля перевода, который создает экземпляр шаблона.Поэтому, когда вы говорите t.Save(obj);
, эта единица перевода должна иметь доступ к определению Save
.Обычно это достигается путем включения определений шаблонов функций в сам файл заголовка.
Причина этого заключается в том, что шаблоны - это не обычный код, который компилируется и может быть позднее связан по желанию.Скорее, шаблоны являются инструментом генерации кода , который генерирует необходимый код по запросу - автоматическую версию копирования / вставки с последующим поиском и заменой, если хотите.
Следовательно,Фактически скомпилированный код для вашей функции Save(ClassDerivedFromInterface&)
не появится, пока вы не напишите эту строку.Если видно только объявление шаблона функции, то шаблон создает объявление только конкретной функции, но не ее тела, и поэтому во время ссылки вы заметите, что функция отсутствует.
Напомним,Сами шаблоны не могут быть скомпилированы, это могут быть только их конкретные экземпляры, и вы должны обратить внимание на то, чтобы конкретные экземпляры всегда были доступны при их создании.Явное создание экземпляра в том виде, в котором оно есть, работает и позволяет вам упаковать несколько конкретных экземпляров в отдельный TU, но, как правило, это сложно поддерживать и не масштабируемо, и существуют другие недостатки явного создания экземпляров, которых вы избегаете, когда вы позволяете компилятору создавать неявно.Поэтому обычно лучше упаковать все ваши определения в заголовочный файл.