这些是我的文件:
-------- [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
我可以使用命令g ++ -c main.cpp和g ++ -c c.cpp等为所有上述文件生成“.o”文件。 但是当我尝试将“.o”文件与g ++ -o car c.o main.o v.o链接时 我收到这个错误:
main.o: In function `main':
main.cpp:(.text+0x17): undefined reference to `void C::call<Merc>(Merc&)'
collect2: ld returned 1 exit status
当我取消注释main.cpp中的#include“c.cpp”行时,错误消失了,但我觉得以这种方式包含cpp文件可能是不好的做法。我做错了吗?在创建单独的目标文件并链接它们时,是否有更好的方法来满足模板化声明? p.s:我在更复杂的类结构中使用模板化函数。这里显示的只是一个小例子,为了向您展示我所面临的那种错误。
答案 0 :(得分:2)
我相信这是因为当你编译c.cpp
时,编译器不知道它需要为C::call<Merc>(Merc&)
生成代码,而当你编译main.cpp
时它没有C::call<T>(T&)
的定义,用于实例化C::call<Merc>(Merc&)
。
模板定义本质上是语义宏,与预处理器的#define
词法宏非常相似,它们必须在使用它们的编译单元中可见。
答案 1 :(得分:1)
解决此问题的方法是
一个。从c.cpp AND
中删除'#include“c.hpp”'湾在'c.hpp'末尾加上'c.cpp'(听起来很奇怪'#include“c.pp”')
这样,模板定义可供每个包含'c.hpp'的翻译单元使用,而无需在每个.cpp文件中明确这样做。这称为'inclusion model'
答案 2 :(得分:0)
实际上,您不能在当前C ++的单独文件中包含相关的模板声明和定义。您应该在一个文件中完全定义C类。