在编译期间,模板化函数被报告为“未定义的引用”

时间:2010-10-07 05:16:10

标签: c++ templates makefile linker object-files

这些是我的文件:

-------- [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:我在更复杂的类结构中使用模板化函数。这里显示的只是一个小例子,为了向您展示我所面临的那种错误。

3 个答案:

答案 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类。