C++模板不支持分离编译的问题
前言
分离编译模式
一个项目如果有多个源文件.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<iostream>
#include"fun.h"
int main()
{
cout<<fun(1)<<endl;
return 0;
}
结果:正常编译,正常运行;
模板函数的分离编译(出错)
各文件代码如下:
//"fun.h"
template<class T>
int fun(T a);
//"fun.cpp"
template<class T>
int fun(T a)
{
return a;
}
//main.cpp
#include<iostream>
#include"fun.h"
int main()
{
cout<<fun(1)<<endl;
return 0;
}
结果:编译出错
分析
实例化
实例化是指编译器使用函数(或者是类)模板为特定类型生成函数(类)定义。编译器不会为函数(或者类)模板生成定义,只有当我们为函数(或者类)模板指定了一个特定类型时,编译器才会生成。编译器为特定类型的函数(或者类)模板生成定义的行为被称为实例化。
普通函数在编译时就实例化,生成fun.obj目标文件;
之后main.cpp编译的时候,看到了fun.h的头文件中fun函数的声明,没有看到定义,链接器,在链接时就看到了fun.obj目标文件中fun函数实例出来的对象,进行链接;
C++规定模板函数只有在使用时实例化:
fun.cpp定义了模版方法,但是没有使用,因此目标文件fun.obj中不会有实例化的模版方法。
而main.cpp只能看到函数的声明,并且链接器链接时也找不到fun.obj中的fun函数对象, 因此报错;
解决方式
- 将模板的声明和定义放在一个.hpp文件里,或者像C语言一样,放在两个.h中 ,总之让编译器在一个源文件,比如main.c中能同时看到模板的定义和初始化就行;
- extern 控制实例化
拓展–extern关键字
extern"C"
extern “C”的作用就是告诉C++编译器,将指定的函数用C规则编译;
因为函数重载,函数名修饰规则不同的原因,如果C++中调用C文件,编译可能会出错;
extern "C"的主要功能是为了能够正确实现C++代码调用C语言代码。
extern+变量
声明某个变量或者函数在外部文件,直接拿来用;
extern+模板–控制实例化
上面说的模板使用时实例化,那工程很大,每个文件都需要用这个模板。都需要实例化一份?额外开销会非常严重。
这时候可以extern修饰他,意味着其他文件中的模板func也能在这里用,就是说公用一份,只需要在一个源文件中实例化这个模板即可,生成的obj其他文件能链接到!
提一嘴 新标准的显示实例化指定类型,也能解决上面模板多文件实例化太多造成额外开销的问题
相关文章
- C++ 虚函数表解析
- C++ 获取类成员函数地址,并通过地址调用函数
- C++模板之可变模板参数
- 2015级C++第2周实践项目
- C++入门学习——模板
- 【C++】模板
- 56 C++ - 模板概论
- C++ 模板详解 肥而不腻
- 类与对象:C++编程知识回顾与拓展 第一篇
- 《C++覆辙录》——1.8:未能区分可访问性和可见性
- 《C++ Templates中文版》——第2章 函数模板
- 《C++ Templates中文版》——2.3 模板参数
- 【C++】关于C++模板的分离编译问题
- 基于C++实现(控制台)模拟网上购书订单管理系统【100010011】
- 使你的C/C++代码支持Unicode(CRT字符串处理的所有API列表,甚至有WEOF字符存在)
- C++反射机制:可变参数模板实现C++反射(使用C++11的新特性--可变模版参数,只根据类的名字(字符串)创建类的实例。在Nebula高性能网络框架中大量应用)
- C++中的模板
- C++编程——函数模板
- C++类模板的声明和定义为什么要放在同一个文件
- C++学习笔记12-模板1
- C++ 深入理解模板实现多态思想
- LeetCode //C++ Palindrome Number
- C++模板全特化、偏特化
- C/C++ 指针常量和常量指针