C++ 模板的编译与链接
来源:互联网 发布:linux 跨机器拷贝文件 编辑:程序博客网 时间:2024/06/16 12:53
模板是C++泛型编程的基础,一个模板就是一个创建类或者函数的公式;在具体使用时,我们需要将模板参数转化为具体类型,比如int,float,Vector以及自定义类型;这种转换过程发生在编译阶段。
定义模板
假如我们需要完成一个数值幂次方函数的功能,这个数组可以是int,也可以是float;我们的函数分别如下:
整型值的幂次函数:
int Power(int base, int index){ if (0 == index) return (int)1; if (0 > index) return(int)0; int result = base; while (--index) { result *= base; } return result;}
浮点型的幂次函数:
float Power(float base, int index){ if (0 == index) return (float)1; if (0 > index) return(float)0; float result = base; while (--index) { result *= base; } return result;}
可以发现这两个函数基本一样,唯一的差异就是参数和返回值类型不同,函数体完全一致;若还需要针对long型,long long型,我们需要写两份几乎一样的代码。
针对这种情况,C++给出了模板技术,代码编写阶段类型先不确定;在编译器编译时根据函数入参类型再确定,从而生成具体的函数版本。
函数模板
函数模板定义
函数模板的定义如下,由template关键字,一对尖括号组成,T是由typename 标识的不确定类型,编译器会在编译阶段生成具体的函数版本。
template<typename T>T Power(T base, int index){ if (0 == index) return (T)1; if (0 > index) return(T)0; T result = base; while (--index) { result *= base; } return result;}
实例化函数模板
当我们调用一个函数模板时,编译器会根据函数实参来推断模板的具体类型,然后根据这个类型实例化这个类型的版本函数。比如:
(1) cout << "power(2,3):" << Power(2,3) << endl;(2) cout << "power(2.1,3):" << Power(2.1f,3) << endl;
编译器在编译时,遇到语句(1),可以推断出模板实参的类型为int,编译器则开始生成入参为int型的函数版本;同理,遇到语句(2)则生成入参为float型的函数版本;
它们的函数声明如下:
(版本一)int Power(int base, int index)(版本二)float Power(float base, int index)
类模板
类模板(Class template)是用来生成类的蓝图,其原理基本和函数模板基本一致;所不同的是,使用类模板时,我们必须显示指定类模板的类型信息。
类模板定义:
类模板的定义如下:
template <typename T>class CThree{public: CThree(T a, T b, T c) ; T Min(); T Max();private: T m_a; T m_b; T m_c;};
类模板实现:
需要注意的是, 每个成员函数前面都要加上 template< class T >,而且类的名称应该使用CThree< T >.示例代码如下:
template<class T>T CThree<T>::Min(){ T MinVal = m_a < m_b ? m_a : m_b; return MinVal < m_c ? MinVal :m_c;}template<class T>T CThree<T>::Max(){ T MaxVal = m_a > m_b ? m_a : m_b; return MaxVal > m_c ? MaxVal :m_c;}template<class T>CThree<T>::CThree(T a, T b, T c):m_a(a),m_b(b),m_c(c){ return;}
实例化类模板
类模板和函数模板一样,也存在实例化的过程,当编译器遇到语句(1)(2)时,编译器则生成int型和float型的类版本,这两个版本是相互独立的类,不会相互影响。
(1) CThree<int> IntInstance(1,2,4);(2) CThree<float> FloatInstance(1.1f,2.2f,4.4f);
模板编译与链接
现在就来看看,编译器对模板是如何编译和链接吧;
当编译器遇到一个template时,不能够立马为他产生机器代码,它必须等到template被指定某种类型。也就是说,函数模板和类模板的完整定义将出现在template被使用的每一个角落,比如遇到上述中的4个语句时,才能确定编译内容,否则编译器没有足够的信息产生机器代码。
对于不同的编译器,其对模板的编译和链接技术也会有所不同,其中一个常用的技术称之为Smart,其基本原理如下:
1. 模板编译时,以每个cpp文件为编译单位,实例化该文件中的函数模板和类模板
2. 链接器在链接每个目标文件时,会检测是否存在相同的实例;有存在相同的实例版本,则删除一个重复的实例,保证模板实例化没有重复存在。
比如我们有一个程序,包含A.cpp和B.cpp,它们都调用了CThree模板类,在A文件中定义了int和double型的模板类,在B文件中定义了int和float型的模板类;在编译器编译时.cpp文件为编译基础,生成A.obj和B.obj目标文件,即使A.obj和B.obj存在重复的实例版本,但是在链接时,链接器会把所有冗余的模板实例代码删除,保证exe中的实例都是唯一的。编译原理和链接原理,如下所示:
- 模板的编译与链接
- C++ 模板的编译与链接
- C语言的编译与链接
- c的编译链接与执行
- 【C++】gcc/g++ 链接库的编译与链接
- C语言-编译与链接
- C语言编译与链接
- C编译与链接 札记
- linux C编程入门之静态链接库、动态链接库的编译与链接
- 【C】程序的编译与链接--简单介绍
- c 程序的编译链接
- C的编译链接过程
- c++编译链接模板
- 【C++】模板的分类编译
- C/C++ 程序编译与链接的过程详解(静态链接)
- C/C++编译与链接过程
- C/C++编译链接与装载深入浅出
- 编译与链接的知识
- ML的45问(4)——评估假设、贝叶斯与PAC可学习
- RMQ求区间最值
- Java集合list删除重复元素问题
- [中国剩余定理]Hdu 1573——X问题
- gitlab使用
- C++ 模板的编译与链接
- React-----form(表单)
- 服务器(5)--搭建Solr集群+搭建Zookeeper集群(下篇)
- 排序算法之--选择排序
- HTML笔记3
- Linux学习笔记 --Firewalld
- 2017 计蒜之道 初赛 第六场 微软大楼设计方案(中等)
- Java基础教程3-Java中注释写法
- 用AJAX与后台进行交互