C++模板
创始人
2024-03-31 20:16:39
0

目录

​一、什么是模板

1.什么是模板

2.模板的分类

二、函数模板

1.泛型和函数模板

2.函数模板的格式

三、类模板

四、实例化

1.隐式实例化

2.显式实例化

3.隐式类型转换

4.模板参数的匹配原则


一、什么是模板

1.什么是模板

模板(Template)指C++程序设计设计语言中采用类型作为参数的程序设计,支持通用程序设计。C++ 的标准库提供许多有用的函数大多结合了模板的观念,如STL以及IO Stream。模板是C++支持参数化多态的工具,使用模板可以使用户为类或者函数声明一种一般模式,使得类中的某些数据成员或者成员函数的参数、返回值取得任意类型。

2.模板的分类

模板分为函数模板和类模板,函数模板针对参数类型不同的函数;类模板针对数据成员和成员函数类型不同的类。

模板支持与了类型无关的代码的编写。

二、函数模板

1.泛型和函数模板

编写与类型无关的通用代码,是代码复用的一种手段。

比如说,我们定义一个交换intl类型元素值的函数。

void swap(int& a, int& b)
{int temp = 0;temp = a;a = b;b = temp;
}

这个函数可以交换int类型的变量值,但是只能操作int类型。如果我们需要交换double类型的变量,按照C++的逻辑就需要再次定义一个新的重载函数。

void swap(double& a, double& b)
{double temp = 0;temp = a;a = b;b = temp;
}

实现所有类型变量的交换需要写太多逻辑相同的函数,过于冗余。那么,如果我们不指定这个参数的类型,用一个泛型去替代这些类型,让编译器去推导这个参数的具体类型,那么我们就只需要一个函数定义了。

这样的泛型函数就叫做模板,内部变量的类型叫做泛型。

2.函数模板的格式

template//typename也可以换成class
返回值类型 函数名 ( 参数列表 )
{}
template//用template关键字定义泛型
void swap(T1& a, T1& b)//内部变量也用泛型
{T1 temp = 0;temp = a;a = b;b = temp;
}

可以定义多个泛型T1、T2、T3等等,一个泛型只能推导出一个具体类型。T1可以推导为int类型,但是不能又推导为int,又推导为其他类型。

三、类模板

我们定义一个没有完全写好的栈

#define TYPE int
class Stack
{
public:Stack():_a((TYPE*)malloc(sizeof(TYPE)* 4)),_size(0), _volume(0){}void push(TYPE data){_a[_size++] = data;}
private:TYPE* _a;int _size;int _volume;
};

虽然通过改变TYPE对应的类型可以改变存储数据的类型,但是如果我们想同时使用一个储存int类型元素的栈和一个储存double类型元素的栈,那么还需要定义另一个栈的类,依旧冗余。所以类似于函数,类也可以使用泛型。这种使用泛型的类也叫做类模板,与函数模板相似。

template
class Stack
{
public:Stack():_a((T1*)malloc(sizeof(T1)* 4)),_size(0), _volume(0){}void push(T1 data){_a[_size++] = data;}
private:T1* _a;int _size;int _volume;
};

四、实例化

1.隐式实例化

函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数和类的声明,相当于建筑的图纸,只有使用到这个函数和类时才会定义。所以其实模板就是将本来应该我们做的重复的事情交给了编译器。

简单说就是本来我们应该多去写的Swap函数和Stack类的重复工作去给编译器做了。

这是我们之前的函数模板

template//用template关键字定义泛型
void swap(T1& a, T1& b)//内部变量也用泛型
{T1 temp = 0;temp = a;a = b;b = temp;
}

对于不同类型的变量进行swap,当编译器遇到符合模板但没有定义的函数,编译器就会自己生成一个对应的重载函数,如果这个函数之前定义过那就使用之前定义过的函数。

template
void swap(T1& a, T1& b)
{T1 temp = 0;temp = a;a = b;b = temp;
}
int main()
{int a = 1;int b = 2;swap(a,b);//交换两个int变量a和b,编译器会根据模板定义一个int类型的交换函数,如下://void swap(int& a, int& b)double c = 1.0;double d = 2.0;swap(c,d);//交换两个double变量c和d,编译器会根据模板再次定义一个double类型的交换函数,如下://void swap(double& a, double& b)int e = 1;int f = 2;swap(e,f);//再次交换两个int变量e和f,编译器会继续使用之前定义的int类型交换函数//void swap(int& a, int& b)return 0;
}

最后的结果还是定义了很多不同类型的重载函数,与我们自己定义许多不同类型的函数的结果是一样的。但是这时不再需要程序员去一个一个类型定义函数,大大简化了程序的代码量。

模板对于类也是一样的效果,也会自己定义许多不同类型的类去使用,但是类只支持显式实例化。

2.显式实例化

我们不光可以让计算机自己推断类型,而且也可以自己指定生成哪一种类型参数的函数和类。

template//定义泛型T1,在这里也表示下面的函数中会用到T1
void Swap(T1& a, T1& b)
{T1 temp = 0;temp = a;a = b;b = temp;
}
template//定义泛型T2,T1在前面已经定义了表示会用到T1和T2
void print(T1& a, T2& b)//注意,这个T1经过推导只能对应一个类型,不能在上面的函数中是int下面的是double
{cout << a << ' ' << b << endl;
}
int main()
{int a = 1;int b = 2;double c = 1.0;Swap(a, b);//在函数后面加<类型>就可以指定定义和使用对应类型的函数print(a, c);//<>内部多个类型用,隔开对应上面的templatecout << a << ' ' << b << endl;return 0;
}
//输出:
//2 1
//2 1

之前说过,类只支持显式实例化,不能通过编译器推断。类模板也是一个声明或者说是一个蓝图,只有使用了这个类型的函数或者类才会被定义。

template
class Stack
{
public:Stack():_a((T*)malloc(sizeof(T)* 4)), _size(0), _volume(0){}void push(T data){_a[_size++] = data;}
private:T* _a;int _size;int _volume;
};int main()
{Stack s1;//定义一个储存int类型的类,类型为StackStack s2;//定义一个储存double类型的类,类型为Stacks1.push(1);//int类型栈可以插入数据s2.push(1.0);//double类型栈也可以插入数据return 0;
}

3.隐式类型转换

我们可以清楚地看到T会推导出两个变量类型int和double,此时T还是会推导为int,但是b参数会隐式转化为int,我们知道这个转换的临时参数是有常性的,所以需要用const修饰。

template
T Add(const T& left, const T& right)
{return left + right;
}int main()
{int a = 10;double b = 20.2;cout << Add(a, b) << endl;//调用int类型Add函数,b生成一个临时int常量传递给函数return 0;
}

在不能完成隐式类型转换时,程序就会报错。

4.模板参数的匹配原则

  • 一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数
  • 对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模 板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板
  • 模板函数不允许自动类型转换,但普通函数可以进行自动类型转换

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...