C++模板的分离编译问题

本文主要是了解一下为什么模板的定义和声明不能分开,需要简单了解一下编译的四个阶段。

一、理解编译大致流程

整个编译流程分为:预处理、编译、汇编、链接,这里以源文件main.cpp文件为例。

  • 预处理:对源文件进行宏替换、去注释、头文件展开,生成main.i文件。(此时的main.i文件依旧是cpp文件)
  • 编译:对main.i文件进行语法语义检错,如果没有错误将其转换为汇编代码main.s文件。(此时的main.s文件是汇编代码)
  • 汇编:将main.s文件解释为二进制文件main.o。
  • 链接:在main.cpp中调用了函数,同时头文件展开时将函数的声明也引入到了main.cpp文件中,但是此时并没有函数的实现(也可以叫定义)。因此在函数的调用处其实还没有处理完,需要链接到源文件所使用的库文件中,去寻找该函数的实现,将函数的入口地址添加到函数调用处。这就是链接阶段要做的事情。

这里再提一嘴,同一个工程中的不同源文件的编译是独立的,互不干扰。

二、普通函数分离编译

结合下面这个场景来理解。

  1. 在头文件func.h中声明了一个普通函数p
  2. 在源文件func.cpp中引入func.h,对函数p进行定义
  3. 在源文件main.cpp文件中调用函数p

编译阶段编译器的流程。

  • 预处理:在main.cpp和func.cpp中进行宏替换和头文件展开,生成main.i和func.i文件。
  • 编译:对main.i和func.i进行语法检测,然后生成汇编文件main.s和func.s文件
  • 汇编:将汇编文件main.s和func.s解释为二进制文件main.o和func.o
  • 链接:在编译时,由于main.cpp中没有函数实现,因此函数调用还未处理,编译器认为这个函数p的实现在其他源文件中,在链接阶段会去其他源文件找,然后就在func.o中找到了,然后将函数地址填充。

三、模板分离编译

下面将普通函数换成模板函数来了解一下。

  1. 在头文件func.h中声明了一个模板函数p
  2. 在源文件func.cpp中引入func.h,对函数p进行定义
  3. 在源文件main.cpp文件中调用函数p

这里有个小知识,C++中模板在没有调用的时候不会实例化!!!

来看一下编译阶段流程。

  • 预处理:在main.cpp和func.cpp中进行宏替换和头文件展开,生成main.i和func.i文件。
  • 编译:对main.i和func.i进行语法检测,然后生成汇编文件main.s和func.s文件
  • 汇编:将汇编文件main.s和func.s解释为二进制文件main.o和func.o
  • 链接:在编译时,由于main.cpp中没有函数实现,因此函数调用还未处理,编译器认为这个函数p的实现在其他源文件中,在链接阶段会去其他源文件找。 但是,此时func.o中并没有p的实现!!!why? 因为func.cpp中并没有调用函数p,因此func.o中自然没有p函数的实现,因此,这时候编译器在别的源文件中就找不到p函数的实现,那么怎么可能链接成功呢?
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值