模板为什么不能分离编译

Posted 白龙码~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板为什么不能分离编译相关的知识,希望对你有一定的参考价值。

文章目录

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

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

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

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

解决方法

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

以上是关于模板为什么不能分离编译的主要内容,如果未能解决你的问题,请参考以下文章

(C++)模板分离编译面对的问题

C++初阶:模板进阶非类型模板参数 | 模板的特化 | 模板分离编译

C++初阶:模板进阶非类型模板参数 | 模板的特化 | 模板分离编译

C++初阶:模板进阶非类型模板参数 | 模板的特化 | 模板分离编译

C++模板进阶操作 —— 非类型模板参数模板的特化以及模板的分离编译

各种坑