模板的声明和定义 头文件与源文件

今天,写了一个List的模板类,然后把它的声明和定义分别放在头文件和源文件中,发现编译不通。然后,就有疑问了,一是为什么那些普通类我们分为头文件和源文件能编译通过,二是模板为什么不行,所以这个编译究竟做了什么,这才是我的问题。

当我们对一个solution右键选择生成的时候,会对所有的.cpp进行编译(我感觉哈),每个对应生成一个.obj文件。当cpp进行编译时,那种有include头文件的,就是将头文件中的内容直接copy到cpp。隐约记得之前上汇编的课的时候讲过,会生成一些symbol和地址的对应的表,那么应该是在头文件的声明中,那些函数方法的入口地址就已经确定了,然后当调用时,链接器会在不同的obj中进行链接,找到具体的实现。

但是,在模板中,在编译时他需要被实例化。比如说我在a.cpp中用到了b.h里声明的一个模板类,但是在b.h里并没有该模板的实现,那在编译a.cpp时,它include了b.h,但是b.cpp并不知道自己要被实例化成哪种类型,于是链接器并不能找到对应的地址,所以,编译不通过。

感觉应该是这个样子……

参考:

c++ 模板类 声明和定义都放在.h文件的原因

模板类声明和定义为何要写一起

抄抄:

一个编译单元(translation  unit)是指一个.cpp文件以及它所#include的所有.h文件,.h文件里的代码将会被扩展到包含它的.cpp文件里,然后编译器编译该.cpp文件为一个.obj文件(假定我们的平台是win32),后者拥有PE(Portable  Executable,即windows可执行文件)文件格式,并且本身包含的就已经是二进制码,但是不一定能够执行,因为并不保证其中一定有main函数。当编译器将一个工程里的所有.cpp文件以分离的方式编译完毕后,再由连接器(linker)进行连接成为一个.exe文件。

C++标准明确表示,当一个模板不被用到的时侯它就不该被实例化出来。(如果用分离的cpp实现,他不会实例化)

在分离式编译的环境下,编译器编译某一个.cpp文件时并不知道另一个.cpp文件的存在,也不会去查找(当遇到未决符号时它会寄希望于连接器)。这种模式在没有模板的情况下运行良好,但遇到模板时就傻眼了,因为模板仅在需要的时候才会实例化出来,所以,当编译器只看到模板的声明时,它不能实例化该模板,只能创建一个具有外部连接的符号并期待连接器能够将符号的地址决议出来。然而当实现该模板的.cpp文件中没有用到模板的实例时,编译器懒得去实例化,所以,整个工程的.obj中就找不到一行模板实例的二进制代码,于是连接器也黔驴技穷了。

展开阅读全文

没有更多推荐了,返回首页