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


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

    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文件展开,并根据模板参数来相应地实例化出对应的函数或类。

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

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

    解决方法

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

  • 相关阅读:
    B2R Raven: 2靶机渗透
    java-php-net-python-二手书商城系统计算机毕业设计程序
    React 官网为什么那么快?
    一键部署开源AI(人工智能对话模型)(支持显卡或CPU加内存运行)--ChatGLM-6B
    植物内生细菌——降解石油污染的新方向!
    真卷,隔壁半夜房间还亮着灯,原来在偷偷学习分布式服务框架
    加缪——人生到底有什么意义?生命的意义就是生命本身
    Java Redis多限流
    Fuzz测试 发现软件中的隐患和漏洞的秘密武器
    一个时代的落幕,苹果停产iPod touch
  • 原文地址:https://blog.csdn.net/Wyf_Fj/article/details/126877749