前言
C++与C语言之间其中不同的一点就是C++可以启用模版,为程序员省下了许多近乎重复的代码书写,这篇文章将为你介绍模版初阶的知识,让你能使用基本的模版
1.模版类型
- 1.1 模版意义
模版是一种泛式编程,是用来编写与类型无关的通用代码
- 1.2 模版类型
分为模版函数和类模版
2.函数模版
- 2.1 格式
这里先写出一个例子,我们再进行解析:
template<class T>
T Add(T a, T b)
{
return a + b;
}
可以注意到这是一个加法的函数模版,这里的template<class T>,class是类的一个泛称,T则代表的是具体的类型,可以是int,double,float…….而在template下必须接上一个函数声明或定义,在此函数中,T就代表了返回的类型,a和b的类型
- 2.2 实例化
对于函数模版来说,分为隐式实例化和显示实例化
1.隐式实例化:
template<class T>
T Add(T a, T b)
{
return a + b;
}
int r = add(10, 20);
这里直接填入两个整数,让编译器自己分析参数的类型,从而生成对应的函数,这就是隐式实例化
2.显示实例化:
template<class T>
T Add(T a, T b)
{
return a + b;
}
int r = add<int>(10, 20);
这里我们可以注意到我们在函数名后加上了<int>,这就是在告诉编译器这里的T类型是int,编译器就会生成对应的int类型的Add函数,对于一些函数来说,编译器无法进行自我识别,那就要我们写显示实例化
- 2.3 模版函数和函数重载
在上面几行我们说到了有些函数编译器无法进行自我识别,我们就需要写显示实例化,但这其实是比较麻烦的,更方便的方法是我们直接再写一个重载函数就可以了,这里给出一个例子:
template<class T>
T Add(T a, T b)
{
return a + b;
}
int Add(int* a, int* b)
{
return *a + *b;
}
int main()
{
int a = 10;
int b = 20;
int r = Add(&a, &b);
return 0;
}
你可以去试一试,对于传地址函数模版是无法识别的,所以这里我们直接写一个重载函数就可以了,并且对于模版函数来说,编译器会优先选择已经存在的重载函数,就算模版函数可以成功识别,目的是为了节省编译时间
3.类模版
- 3.1 格式
这里先写出一个例子,我们再进行解析:
template<class T>
class list
{
private:
T _val;
list* _next;
list* _prev;
}
这里给出的是链表的例子,与函数模版相同,T是一个类型,而list中_val的类型就是T,其他的与函数模版基本相同,不做过多描述
- 3.2 实例化
要注意的是,类模版只能显示实例化,没有隐式实例化,这里给出一个例子:
template<class T>
class list
{
private:
T _val;
list* _next;
list* _prev;
}
list<int> v1;
这里我们可以注意到,v1对象的创建是必须要用显示实例化的
4.模版的特点
- 4.1 声明与定义分离问题
一般来说,模版的声明和定义分离在不同的两个.h和.cpp文件中会方式连接错误,编译器无法寻找到对应的定义,从而报错
但是,如果真的想将声明和定义分离在不同的不同的两个.h和.cpp文件中,可以采取显示实例化的方式,例子如下:
// ===== math.h =====
template <typename T>
T add(T a, T b);
// ===== math.cpp =====
template <typename T>
T add(T a, T b) {
return a + b;
}
// 显式实例化:只生成这几个版本的代码
template int add<int>(int, int);
template double add<double>(double, double);
// ===== main.cpp =====
#include "math.h"
int main() {
int x = add(1, 2); // ✅ 链接到 math.cpp 生成的 add<int>
double y = add(1.5, 2.5); // ✅ 链接到 add<double>
// float z = add(1.0f, 2.0f); // ❌ 链接错误!未实例化 float 版本
}
虽然显示实例化有用,但是很不推荐,还不如正常写函数
- 4.2 按需实例化
对于类模版来说,其中可能会写很多的成员函数,但是只要不是有特别大的错误,在这个函数被使用之前,很大可能都不会报错,这就叫做按需实例化
因此,当我们写完一个函数的时候一定要去调试一下,以免今后发生难以挽回的错误
总结
模版在今后会非常频繁的进行使用,像是vector,list,stack的模拟实现等等都会使用,所以一定要打好基础

评论(0)
暂无评论