C++模板(函数模板,模板函数,类模板)

模板初始(利用重载进行内容调换)

什么是模板?

为什么需要使用模板?

用他的目的是什么?

先举一个例子

如果需要调换两个数的位置,代码该怎么写?

最简单的方法肯定是这样的:

#include <iostream>
using namespace std;

void Swap(int &a, int &b)
{
	int tmp = a;
	a = b;
	b = tmp;
}

void main()
{
	int a = 1;
	int b = 2;
	Swap(a, b);
	cout << "a = " << a << ", b = " << b << endl;
	system("pause");
}

写个函数一调换就行了
在这里插入图片描述
那要是现在要求换两个字符呢?

也简单,c++中可以进行函数重载,加一个就行了

#include <iostream>
using namespace std;

void Swap(char &a, char &b)
{
	char tmp = a;
	a = b;
	b = tmp;
}

void Swap(int &a, int &b)
{
	int tmp = a;
	a = b;
	b = tmp;
}

void main()
{
	int a = 1;
	int b = 2;
	Swap(a, b);
	cout << "a = " << a << ", b = " << b << endl;
	char c = 'C';
	char d = 'D';
	Swap(c, d);
	cout << "c = " << c << ", d = " << d << endl;
	system("pause");
}

在这里插入图片描述

那么要是要求double?

没事,加!

不过这样一来感觉好像有点low,缺点也很明显:

1、重载的函数仅仅是类型不同,代码的复用率比较低,而且每有一个新的函数类型就要增加相应的函数

2、代码的维护性比较低,一个出错可能其他的也会出错

那有没有一种方法,可以一步到位?

这就要使用到模板了

模板的目的与要求

模板的目的就是通用

模板的要求是将类型进行参数化

用模板解决调换问题

template<typename Type>
void Swap(Type &a, Type &b)
{
	Type tmp = a;
	a = b;
	b = tmp;
}

看起来差别好像也不大,测试一下

void main()
{
	char a = 'A';
	char b = 'B';
	Swap(a, b);
	cout << "a = " << a << ", b = " << b << endl;
	int c = 1;
	int d = 2;
	Swap(c, d);
	cout << "c = " << c << ", d = " << d << endl;
	double e = 11.11;
	double f = 22.22;
	Swap(e, f);
	cout << "e = " << e << ", f = " << f << endl;
	system("pause");
}

这下是三种类型全部包进去了,再看看结果
在这里插入图片描述
完工,很显然这个函数做到了通用,可以称之为模板

那这是怎么做到的?

改动一下函数,让他显示每次调换时的类型

#include <iostream>
using namespace std;

template<typename Type>
void Swap(Type &a, Type &b)
{
	cout << "Type=" << typeid(Type).name() << endl;
	Type tmp = a;
	a = b;
	b = tmp;
}

void main()
{
	char a = 'A';
	char b = 'B';
	Swap(a, b);
	cout << "a = " << a << ", b = " << b << endl;
	int c = 1;
	int d = 2;
	Swap(c, d);
	cout << "c = " << c << ", d = " << d << endl;
	double e = 11.11;
	double f = 22.22;
	Swap(e, f);
	cout << "e = " << e << ", f = " << f << endl;
	system("pause");
}

在这里插入图片描述
结果显示,当我们是char类型时,所调用的类型就是char,int时便为int ···

即根据类型的不同推出的结果也不同

函数模板

概念

函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生的函数的特定类型版本

格式

template<typename T1 , typename T2 , ... , typename Tn>
返回值类型 函数名(参数列表){}

模板不支持隐式转换

先看下边的代码

#include <iostream>
using namespace std;

int Add(int a, int b)
{
	return a + b;
}

void main()
{
	int ret = Add(1, 2);
	system("pause");
}

这是一个求两个int值相加的代码

现在将其更改

#include <iostream>
using namespace std;

int Add(int a, int b)
{
	return a + b;
}

void main()
{
	int ret = Add(1, 2);
	ret = Add(1.2, 2.3);
	system("pause");
}

发现这样也是能够跑成功的,即在其中发生了隐式转换,将double类型强制转成了int类型,从而能够调用前边的函数

此时再添加一组函数

#include <iostream>
using namespace std;

int Add(int a, int b)
{
	return a + b;
}

double Add(double a, double b)
{
	return a + b;
}

void main()
{
	int ret = Add(1, 2);
	ret = Add(1.2, 2.3);
	system("pause");
}

此时就构成了函数的重载,int类型就调用int类型,double就调用double类型

那如果这么改呢?

#include <iostream>
using namespace std;

double Add(int a, double b)
{
	return a + b;
}

void main()
{
	int ret = Add(1, 2);
	ret = Add(1.2, 2.3);
	system("pause");
}

在这里插入图片描述
在这里插入图片描述
很显然也是能跑成功的

那么要是使用模板呢?

#include <iostream>
using namespace std;

template<typename Type>
Type Add(Type a, Type b)
{
	cout << "Type=" << typeid(Type).name() << endl;
	return a + b;
}

void main()
{
	int ret = Add(1, 2);
	ret = Add(1.2, 2.3);
	system("pause");
}

在这里插入图片描述
可以看到这也是可行的,第一次调用时为int类型,第二次调用为double类型

那再改改呢?

#include <iostream>
using namespace std;

template<typename Type>
Type Add(Type a, Type b)
{
	cout << "Type=" << typeid(Type).name() << endl;
	return a + b;
}

void main()
{
	int ret = Add(1, 2.1);
	system("pause");
}

在这里插入图片描述
此时发现报错了,这就要提到模板一个最大的特点了:

模板不支持隐式转换

原因其实很简单,当使用第一个数和Type结合时,推导出来的类型是int类型,但当第二个数与Type结合时推导出来的却是double类型,此时无法确定类型,即产生了类型的二义性
在这里插入图片描述
在这里插入图片描述
那么如何解决?

方法一: 添加类型

#include <iostream>
using namespace std;

template<typename Type1, typename Type2>
Type1 Add(Type1 a, Type2 b)
{
	return a + b;
}

void main()
{
	int ret = Add(1, 2.1);
	system("pause");
}

在这里插入图片描述
即让第一个数与Type1结合推导出类型int,第二个数与Type2结合推导出类型double,即可解决这个问题

方法二: 强制转换

void main()
{
	int ret = Add((double)1, 2.1);
	system("pause");
}

void main()
{
	int ret = Add(1, (int)2.1);
	system("pause");
}

只要能让他们的类型相同就行

方法三: 自暴自弃(划掉) 显式实例化

void main()
{
	int ret = Add<int>(1, 2.1);
	system("pause");
}

这样在传递的时候直接告诉函数我就是int类型的,也能解决冲突,同样尖括号中的内容也可以换成其他类型

模板函数

模板函数即通过函数模板与传递值类型结合出来的函数

举个例子

template<typename Type>
Type Add(Type a, Type b)
{}

这个就是函数模板↑

传递了
ret = Add (1, 2);
后的函数模板即

int Add(int a, int b)
{}

这个就是模板函数↑

类模板

定义格式

template(class T1, class T2, ... ,class Tn)
class 类模板名
{
	//类内成员定义
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值