2010-10-07 2 views
0

Это мои файлы:шаблонные функции сообщается как "неопределенная ссылка" во время компиляции

-------- [c.hpp] --------

#ifndef _C 
#define _C 

#include<iostream> 
class C 
{ 
public: 
    template<class CARTYPE> void call(CARTYPE& c); 
}; 

#endif 

-------- [c.cpp] --------

#include "c.hpp" 

template<class CARTYPE> void C::call(CARTYPE& c) 
{ 
    //make use of c somewhere here 
    std::cout<<"Car"<<std::endl; 
} 

-------- [v.cpp] --------

class Merc 
{}; 

-------- [main.cpp] --------

#include "c.hpp" 
#include "v.cpp" 
//#include "c.cpp" 

int main() 
{ 
    Merc m; 
    C someCar; 
    someCar.call(m); 

}//main 

Я способен генерировать «.o» файлы для всех вышеперечисленных файлов с помощью команды g ++ -c main.cpp и g ++ -c c.cpp и т. д. Но когда я пытаюсь связать «.o» файлы с г ++ -o автомобиль совместно main.o VO Я получаю эту ошибку:

main.o: In function `main': 
main.cpp:(.text+0x17): undefined reference to `void C::call<Merc>(Merc&)' 
collect2: ld returned 1 exit status 

ошибка исчезнет, ​​когда я раскомментировать #include линии «c.cpp "в main.cpp, но я считаю, что может быть плохой практикой включать этот файл cpp. Я делаю это неправильно? Есть ли лучший способ удовлетворить шаблонные объявления при создании отдельных объектных файлов и их связывании? p.s: Я использую шаблонную функцию в гораздо более сложной структуре класса. То, что показано здесь, является лишь небольшим примером для того, чтобы показать вам ту ошибку, с которой я столкнулся.

+3

См. Http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file –

+0

@Pavel: Решение, на которое вы указали, является точным решением, которое мне нужно , Спасибо :) – Nav

ответ

1

Способ решения этой проблемы:

a. удалить '#include "c.hpp"' c.cpp И

b. включая «c.cpp» в конце «c.hpp» (странное звучание «#include» c.pp »')

Таким образом, определения шаблонов доступны для каждой единицы перевода, которая включает в себя« c.hpp », без явно сделанного в каждом файле .cpp. Это называется 'inclusion model'

+0

Это также вызывает проблемы, если вы развиваете потребность в вещах в c.cpp, которые не должны включаться в каждую единицу перевода. –

+0

@ Тони: О, так что ты тогда делаешь? – Chubsdad

+0

Тогда вам действительно нужно переместить реализацию шаблона в заголовок. Просто думая об одном правиле определения и обо всем этом джазе .... –

2

Я считаю, что это происходит потому, что при компиляции c.cpp компилятор не знает, он должен генерировать код для C::call<Merc>(Merc&), и когда вы собираете main.cpp это не определение C::call<T>(T&) из которых для создания экземпляра C::call<Merc>(Merc&).

Определения шаблонов по существу являются семантическими макросами, так же как лексические макросы препроцессора #define, они должны быть видны в единицах компиляции, которые их используют.

0

По существу, вы не можете иметь связанные объявления шаблонов и определения в отдельных файлах в текущем C++. Вы должны полностью определить класс C в одном файле.

+0

Просто в порядке разъяснения: это справедливо для общего и иллюстрированного случая открытых/защищенных шаблонов, но не обязательно для частных шаблонов. –

+0

Что происходит с классами друзей и частными шаблонами? – nakiya

Смежные вопросы