首页 > 编程语言 > 详细

C++模板声明与实现分开--由此想到的编译,链接原理

时间:2019-08-12 12:58:52      阅读:256      评论:0      收藏:0      [点我收藏+]

问题来源:当模板文件的实现与声明分开在不同文件中时,链接时会提示找不到相应模板函数,如下

技术分享图片

一,编译和链接的大概原理:

1,编译,遍历工程的所有代码文件,进行文件分析,这里的分析与文件后缀无关,并不是说以CPP文件为依据,源文件后缀名可以改为任何名字。

编译以文件为单位,将此文件#include的所有文件拿进来,写进此文件中,包含进来的东西可能是函数声明,也可能是函数的实现体。

如果#include "test.h",则包含进来的是一些函数和变量的声明,如果 #include "test.cpp",则其中的函数实现代码也被包含进来了。

编译的结果是一个obj文件,如test.cpp编译后是一个test.obj文件,里面是汇编指令。

同时,编译器有了该文件的一个清单,里面保存了 【函数签名(声明)】到【函数体实现】的映射

2,链接,对所有的obj文件进行拼接。

为什么要拼接?对于每个obj文件,其中若调用了其它文件的函数(外部调用),就需要知道此外部函数的具体实现,这在编译时是不关心的。

这时候去所有obj文件中查找此外部函数的实现体,若有两个以上的obj都有此实现,则链接出错,因为函数实现不唯一了,这不允许。此错误就是常见的

XXX 已经在 xxx.obj中定义了,如下:

技术分享图片

若查找结果唯一,则将此外部函数的实现插入到调用处。

 二,实例分析

1,一个头文件被多个CPP包含时编译链接正确,一个CPP文件被多个其它CPP文件包含时编译正确,链接出错,报错为 XXX 已经在 xxx.obj中定义。

因为CPP中有函数的实现体,每被包含一次就多了一个实现,导致一个函数在不同CPP文件中被多次实现,重复了。

头文件被多次包含为什么没问题?关键是每个头文件开头都有宏 #pragma once,该宏确保了头文件只会被包含一次

2,模板文件的特殊性。

模板文件只有在实例化时才能确定其具体的实现体,所以如果将模板文件的声明和函数体分开在.h和.cpp中,当编译cpp时,并不会产生函数的具体实现体。当在其它文件中#include "template.h"时,会提示找不到函数的定义。

解决方法:在需要使用模板函数的地方,#include "template.cpp",即包含它的CPP文件,而不是.h文件。

原因:使用模板函数的地方,比如 addobj<cube>(),传了具体的模板类型给函数,这样模板函数就能到CPP文件中找到对应的实现体将cube传给模板参数而实例化了。

C++模板声明与实现分开--由此想到的编译,链接原理

原文:https://www.cnblogs.com/timeObjserver/p/11338982.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!