2010-10-07 61 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等等。 但是当我尝试连接使用g ++ -o汽车合作main.o沃 的名为“.o”文件,我得到这个错误:

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 – 2010-10-07 05:18:38

+0

@Pavel:您指出的解决方案是我需要的确切解决方案。谢谢:) – Nav 2010-10-07 06:15:14

回答

1

一种解决这个问题的方法是

a。从c.cpp删除'#include'c.hpp''AND

b。在'c.hpp'(奇怪的声音'#include“c.pp'')结尾处包括'c.cpp'

这样模板定义可用于每个翻译单元,包括'c.hpp'而不是在每个.cpp文件中明确这样做。这就是所谓的'inclusion model'

+0

如果您对c.cpp中不应包含在每个翻译单元中的东西的需求发展,它也会导致麻烦。 – 2010-10-07 05:55:35

+0

@Tony:哦,那你现在怎么办? – Chubsdad 2010-10-07 06:01:31

+0

然后,您确实必须将模板实现移到标题中。只是想到一个定义规则和所有爵士乐...... – 2010-10-07 06:38:21

2

我相信这是因为当你编译c.cpp编译器不知道它需要为C::call<Merc>(Merc&)生成代码,当你正在编译main.cpp它不具有的C::call<T>(T&)从中定义来实例化C::call<Merc>(Merc&)

模板定义本质上是语义宏,与预处理器的#define词法宏非常相似,它们必须在使用它们的编译单元中可见。

0

实质上,你不能在当前C++的单独文件中拥有相关的模板声明和定义。你应该在一个文件中完全定义C类。

+0

只是通过澄清:对于公共/受保护模板的常见和已说明的情况而言,这是正确的,但对于专用模板不是必需的。 – 2010-10-07 05:57:01

+0

朋友类和私人模板会发生什么? – nakiya 2010-10-07 06:06:36

相关问题