C++模板不支持分离编译的问题
创始人
2024-05-16 01:03:49
0

目录

    • 前言
    • 分离编译模式
    • 普通函数的分离编译(正常)
    • 模板函数的分离编译(出错)
    • 分析
    • 解决方式
    • 拓展--extern关键字
      • extern"C"
      • extern+变量
      • extern+模板--控制实例化

前言

分离编译模式

一个项目如果有多个源文件.c组成,每个源文件单独编译,形成目标文件最后通过链接器将所有的目标文件链接起来,形成一个可执行的文件。

这种就是.h头文件和.c源文件配合使用的模式;

分离式编译的优势

如果工程巨大(比如linux内核源码) , 当你只修改了其中一个工程文件.c的时候,重新编译只需要编译改动过的文件就可以了,不需要将全部工程文件.cpp全部重新编译。

普通函数的分离编译(正常)

各文件代码如下:

//"fun.h"
int fun(int a);//"fun.cpp"
#include"fun.h"
int fun(int  a)
{return a;
}//main.cpp
#include
#include"fun.h"int main()
{cout<

结果:正常编译,正常运行;

模板函数的分离编译(出错)

各文件代码如下:

//"fun.h"
template
int fun(T a);//"fun.cpp"
template
int fun(T a)
{return a;
}//main.cpp
#include
#include"fun.h"int main()
{cout<

结果:编译出错

在这里插入图片描述

分析

实例化

实例化是指编译器使用函数(或者是类)模板为特定类型生成函数(类)定义。编译器不会为函数(或者类)模板生成定义,只有当我们为函数(或者类)模板指定了一个特定类型时,编译器才会生成。编译器为特定类型的函数(或者类)模板生成定义的行为被称为实例化。


普通函数在编译时就实例化生成fun.obj目标文件;

之后main.cpp编译的时候,看到了fun.h的头文件中fun函数的声明,没有看到定义,链接器,在链接时就看到了fun.obj目标文件中fun函数实例出来的对象,进行链接;


C++规定模板函数只有在使用时实例化:

fun.cpp定义了模版方法,但是没有使用,因此目标文件fun.obj中不会有实例化的模版方法。

main.cpp只能看到函数的声明,并且链接器链接时也找不到fun.obj中的fun函数对象, 因此报错;


解决方式

  1. 将模板的声明和定义放在一个.hpp文件里,或者像C语言一样,放在两个.h中 ,总之让编译器在一个源文件,比如main.c中能同时看到模板的定义和初始化就行;
  2. extern 控制实例化

拓展–extern关键字

extern"C"


extern “C”的作用就是告诉C++编译器,将指定的函数用C规则编译;

因为函数重载,函数名修饰规则不同的原因,如果C++中调用C文件,编译可能会出错;

extern "C"的主要功能是为了能够正确实现C++代码调用C语言代码


extern+变量

声明某个变量或者函数在外部文件,直接拿来用;


extern+模板–控制实例化

上面说的模板使用时实例化,那工程很大,每个文件都需要用这个模板。都需要实例化一份?额外开销会非常严重

这时候可以extern修饰他,意味着其他文件中的模板func也能在这里用,就是说公用一份,只需要在一个源文件中实例化这个模板即可,生成的obj其他文件能链接到!

提一嘴 新标准的显示实例化指定类型,也能解决上面模板多文件实例化太多造成额外开销的问题

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
【PdgCntEditor】解... 一、问题背景 大部分的图书对应的PDF,目录中的页码并非PDF中直接索引的页码...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
修复 爱普生 EPSON L4... L4151 L4153 L4156 L4158 L4163 L4165 L4166 L4168 L4...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...