绪论
思想决定行动,行动养成习惯,习惯形成品质,品质决定命运。——陶行知
本章讲的是c++的初阶模板,全文不算代码字数少的可怜,但模板是我们c++必须学的一个宝物,他的出现可是c++的飞跃性成就!下面将主要以代码的方式来进行语法学习。
话不多说安全带系好,发车啦(建议电脑观看)。
附:红色,部分为重点部分;蓝颜色为需要记忆的部分(不是死记硬背哈,多敲);黑色加粗或者其余颜色为次重点;黑色为描述需要
思维导图:
要XMind思维导图的话可以私信哈
目录
1.泛型编程
2.函数模板
2.1实现模板的原理
2.2函数模板的实例化
3.类模板
1.泛型编程
知识点:
泛型编程:编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础有点抽象。
他们在一些重复性很强的代码上虽然使用函数重载可以实现,但是终究有不好的地方,重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函数,代码的可维护性比较低,一个出错可能所有的重载均出错。
具体那下面的代码具体展示:
下面是swap交换函数,此时就是对不同的类型就需要不同的交换函数:void swap(int& x, int& y) { int tmp = x; x = y; y = tmp; } void swap(char& x, char& y) { char tmp = x; x = y; y = tmp; } void swap(float& x, float& y) { float tmp = x; x = y; y = tmp; } // ......
对此c++,为了解决这个问题就提出了一个新语法:模板(模板就像一个模具一样我们创造出来的东西形状都一样,只是我们放进去的材料不同最终出来的也东西就有所不同。在上面的交换函数中,交换的方法是一样的,只是他们的类型不同,也就是所谓的换汤不换药还是老一套,所以就能用模板来快速的实现相类函数的创建)。
2.函数模板
知识点:
函数模板概念:函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。
模板的语法:template<typename T1, typename T2 ...> 、 template<class T, ....>
返回值类型 函数名(参数列表)
{}
- 其中class 和 typename是一样的效果我们都可以使用
- 模板需要和需要模板的函数紧挨着一起出现。模板参数的使用范围就是在其下方的函数/类的域中。
使用练习(注意看注释):
//template<class Ty>和下面的是效果一样的,并且内部的Ty是和变量名一样可以自行diy的
template<typename T>
void Swap(T& x, T& y) {
T tmp = x;
x = y;
y = tmp;
}
// 我们可以定义多个模板参数,来分开识别使用,防止出现两个参数的类型不同的情况
template<class T1,typename T2>
void Func(T1& x, T2& y)//此处定义了两个模板参数,就能对应对当两个类型不同的情况
{
cout << x << ' ' << y << endl;
}
int main()
{
int a = 0 , b = 1;
double c = 1.1, d = 2.2;
Swap(a, b);
Swap(c, d);
int e = 10;
double f = 10.4;
Func(e, f);
return 0;
}
细节:
2.1实现模板的原理
模板的实现原理其就和现实中的很像,通过一个模具,重复多次某种类似的过程,而模具就像上面代码中的模板下面的函数一样,在这过程中通过这个模具会创建出多个看不见的重载的函数,其实本质还是创建了多个函数并且去调用了这些函数,只是这实现过程被编译器代替了而已(模板的实例化)。
注意:虽然他们用的是同一个模板,但是他们调用的函数时不一样的!
附:其实在c++库中已经为我们写好了这个交换函数,所以说从后面开始我们不需要在自己去实现swap函数,直接用就可以 , swap(变量,变量);
2.2函数模板的实例化
- 用不同类型的参数使用函数模板时,称为函数模板的实例化。
- 模板参数实例化分为:隐式实例化和显式实例化
- 隐式实例化:给参数去直接直接识别类型,然后给到模板参数创建函数,就如上面的练习一样。
- 显示实例化:自己直接给函数的模板参数在调用前确定类型
举例练习:
显示实例化的写法:
在函数和参数之间加上方括号 , 并且在内部加上类型 如 :Func<int>(a,b)。
具体如下:
template<typename T>
T* Alloc(int n)
{
return new T[n];
}
int main()
{
int* ptr = Alloc<int>(10);//此时的<int>就是一个显示的实例化,直接给这个函数的模板参数定义了类型int
return 0;
}
3.类模板
知识点:
- 类模板的定义格式:类模板和函数模板使用方法和功能都几乎一样,只是用处有些许的不同(具体将通过代码展示)
- 对于函数模板来说他的作用域是挨着的函数局部域,而对于类模板来是作用于紧挨着的整个类域里面。
细节:
如果加上了类模板的话,就会改变其类的类型:
类型: 类名<所有模板参数>
类的类名还是一样
练习使用(再次理解,注意注释):
template<typename T>
class Stack
{
public:
Stack(int capacity = 4)
{
_arr = new T[capacity];
int _size = 0;
int _capacity = capacity;
}
void Push(const T& x);
~Stack()
{
delete _arr;
_size = 0;
_capacity = 0;
}
private:
T* _arr;
int _size;
int _capacity;
};
template<typename T>
void Stack<T>::Push(const T& x)//此时我们定义全局函数时,需要我们指定类域才能使用其内部的成员
//而对于函数模板来说,此时的类型也该变成 Stack<模板参数>
{
//CheckCapacity()
_arr[_size] = x;
_size++;
}
int main()
{
Stack<int> st1;//显示实例化,此处必须加上这个显示...
Stack<double> st2;//double
//这样写我们就不用像cyy那样需要去改变 TypeDate 了
//并且,可以同时使用多种类型的栈
//C语言不能同时拥有,因为C语言的TypeDate只能在一处使用,就导致定死后不能用于
//另外一处新的类型的对象中,而模板就能突破这个界限,创建多个类型不同功能一样的函数
return 0;
}
本章完。预知后事如何,暂听下回分解。
如果有任何问题欢迎讨论哈!
如果觉得这篇文章对你有所帮助的话点点赞吧!
持续更新大量C++细致内容,早关注不迷路。