模板为什么不能分离编译
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)尖括号的头文件是系统文件,双引号""的头文件是自定义文件。
(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++初阶:模板进阶非类型模板参数 | 模板的特化 | 模板分离编译