当前位置:   article > 正文

模板分离编译问题(函数模板的声明和定义无法放在两个文件的原因分析)_模板函数多文件间声明和调用

模板函数多文件间声明和调用

为了方便维护,我们一般将函数声明放在 .h 文件,将函数定义放在 .c 或者 .cpp 文件。但是 函数模板是无法将声明和定义放在两个文件的,最直接的理由是函数模板因为没有被实例化,编译器不会编译函数模板。


目录

一、案例介绍

二、原因分析

1、预处理

2、编译

3、汇编

4、链接

三、解决方案


一、案例介绍

假设函数模板的声明、定义和调用的位置如下:

  • 函数模板 Add 的声明  ——  Add.h
  • 函数模板 Add 的定义  ——  Add.cpp
  • 函数模板 Add 的调用  ——  main.cpp

二、原因分析

程序运行分为四个阶段我们下面就从这四个阶段分析。我们主要看两个cpp文件,因为h文件在第一阶段就被展开了。

1、预处理

这个阶段的作用主要是头文件展开、宏替换、去掉注释。main.cpp文件、Add.cpp文件可以看作是下面的情况,最终会生成 main.i、Add.i文件。

2、编译

这个阶段的主要作用是语法分析、词法分析、符号汇总等,如果没有问题,则编译生成汇编代码。值得注意的是,函数模板在这里不会被编译。因为编译器根本就不知道Add函数的返回值要占用多大空间

因此,Add.s 中不会出现 Add函数的相关实现,也就不存在对应的函数地址。

3、汇编

这个阶段主要是用上一个阶段汇总的符号(函数名、全局变量等),生成对应的符号表,因为我们实际链接的时候,假如要调用某个函数,起始就是根据符号表去找到对应的函数地址,然后再去执行对应的函数。

注意:Add对应的一栏里填写的 “ ? ” 只是临时的,因为在main函数所在源文件中没有找到Add函数的定义,也就没有对应的函数地址。

4、链接

这个阶段是上述 .o 文件的交互阶段,此时编译器会把所有的 符号表合并,这样的话就构成了一张完整的表格。只不过Add.o 对应的符号表是空的,那么最终的符号表就是

编译器在链接Add函数的时候发现,Add函数没有对应的地址,找不到Add函数,这个时候就会报如下错误,无法解析的外部符号。

三、解决方案

现在问题主要在于,将函数模板的定义单独放在一个文件的时候,编译器不会编译函数模板。

何时会编译Add函数? ==》Add函数模板实例化的时候 ==》 Add函数被调用的时候

也就是说,我们只要把函数模板的定义放在Add函数被调用的地方就可以了。之前在了解模板实例化的时候有这么一个图,当函数模板实例化的时候,此时编译器会生成实实在在的函数。此时编译器就可以在第二阶段编译函数生成对应的汇编代码,然后在第三阶段生成 Add函数的符号表了。

具体操作如下:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/105578?site
推荐阅读
相关标签
  

闽ICP备14008679号