• 模板为什么不能分离编译


    在进入正题之前可以了解一下编译的相关知识。

    gcc/g++

    gcc和g++分别是C和C++的编译器。

    1、预处理(-E)

    预处理阶段进行头文件展开、宏展开、删除注释、条件编译等操作。

    -E选项使得编译器在预处理后就停止编译,比如:gcc -E test.c

    注:默认-E选项不会生成文件,只会将预处理后的文件内容打印出来

    不过我们可以将预处理后的内容重定向至**.i**文件中,如:

    gcc -E test.c -o test.i

    其中,-o是指定将预处理的内容写入某一目标文件中(预处理后应当是.i文件)

    include头文件时引号与尖括号的区别

    1. 区别:

      (1)尖括号的头文件是系统文件,双引号""的头文件是自定义文件

      (2)编译器预处理阶段查找头文件的路径不一样。

    2. 查找路径:

      (1)使用尖括号<>的头文件的查找路径:编译器设置的头文件路径–>系统变量。

      (2)使用双引号""的头文件的查找路径:当前头文件目录–>编译器设置的头文件路径–>系统变量。

    2、编译(-S)

    编译阶段进行词法分析、语义分析,检查语法是否有误,若无误则将代码翻译成汇编语言

    -S选项只进行预处理和编译,并默认生成一个**.s**文件存储编译后的内容,比如:

    gcc -S test.c 或者 gcc -S test.i

    该选项可以处理源文件和.i文件

    3、汇编(-c)

    汇编阶段将汇编语言转为二进制的机器语言。

    -c选项会默认生成一个**.o**文件存储二进制内容,比如:

    gcc -c test.c

    注意:在链接之前不会检查声明的变量和函数是否存在,只会检查语法和某些函数变量是否声明,如果没有声明,则只有警告,目标文件(.o)可以正常生成

    4、链接

    链接阶段进行目标文件的链接工作,如果没有选项的话,gcc默认执行的就是从预处理到链接的全过程,比如:gcc test.c -o test,该指令就会将test.c编译链接并形成可执行文件test。

    分离编译

    一个程序由若干源文件共同实现,每一个源文件单独编译并生成目标文件,最后进行链接形成可执行文件的过程称为分离编译模式。

    为什么模板不能分离编译

    对于模板而言,对其分离编译会出现链接错误,原因是:

    如果我们将模板的声明写在.h文件,将定义写在.cpp文件中,那么在预处理时,.h文件展开,并根据模板参数来相应地实例化出对应的函数或类。

    但是如果我们想要调用的是模板函数或是模板类里的模板成员函数,那么就会出现问题,因为这些函数的定义是在另外一个文件中,在当前文件中,我们需要将这个函数实例化,但是苦在没有定义,而在另一个文件中,函数有定义,但是并不知道应该实例化成什么类型的,因为不同的源文件是分开编译的。因此,到最后的链接阶段,我们调用的模板函数终究因为找不到函数地址而导致报错。

    注:模板属于静态多态,在编译期完成。

    解决方法

    直接在头文件中声明和定义模板。

  • 相关阅读:
    金仓数据库 KingbaseES 插件参考手册 zhparser
    uniapp实现扫一扫功能,扫码成功后跳转页面
    常用面试/笔试开源小项目61~70
    图形学-变换(平移矩阵,旋转矩阵,缩放矩阵,线性变换,放射变换,齐次坐标)
    2024-04-25 问AI: 介绍一下 ISBI 挑战赛
    矩阵等价和向量组等价的一些问题
    TCP 四次挥手,可以直接变成三次?
    高复杂度的城市数字化转型“交响曲”,新华三如何奏响?
    USB2.0 UTMI接口
    第十二届蓝桥杯模拟赛第三期
  • 原文地址:https://blog.csdn.net/Wyf_Fj/article/details/126877749