本文介绍: 上面交换代码可以写成这样。

泛型编程

假如我们要写一个两数交换的函数,按我们之前学的知识我们会这样。

void Swap(int& left, int& right)
{
	int temp = left;
	left = right;
	right = temp;
}

void Swap(double& left, double& right)
{
	double temp = left;
	left = right;
	right = temp;
}
int main()
{
	int a = 1, b = 2;
	//Swap(a, b);
	Swap(a, b);

	double c = 1.1, d = 2.22;
	//Swap(a, b);
	Swap(c, d);

	return 0;
}

这是函数重载,按我们理解,再增加不同类型的数进行交换又要写一个函数,这样就需要不断的去写函数
所以这里就引出了我们接下来要说的泛型编程

函数模板

格式

template<typename T&gt;

template关键字
T模板类型名称可以随便给。

定义多个模板参数
template<typename x, typename y&gt;

上面交换的代码可以写成这样

template<class T&gt;
void Swap(T&amp; x, T&amp; y)
{
	T tmp = x;
	x = y;
	y = tmp;
}
int main()
{
	int a = 1, b = 2;
	//Swap(a, b);
	Swap(a, b);

	double c = 1.1, d = 2.22;
	//Swap(c,d);
	Swap(c, d);

	return 0;
}

它是针对广泛的类型来进行编程的。T具体的类型什么我也不知道

写成这样,无论什么类型数据进行交换都只需要写这一个模板

模板调用的是同一个函数吗?

那现在问题来了,Swap(a, b);和Swap(c, d);调用的是同一个函数吗?
通过调试我们发现好像是这样,但是只看这个是不够的,还是看一下汇编结果发现函数地址不一样,所以肯定不是同一个函数。
在这里插入图片描述

其实我们仔细想想也知道,不可能同一个同一个指令是一样的。那函数要建立栈帧,这两个栈帧大小一样吗?
要交换的数的类型不一样,函数栈帧的大小也肯定不一样。

模板的实现原理

那现在又有一个问题,上面两个swap函数调用的是不是模板?
其实不是,这么说吧!Swap(a, b);编译器判断出a,b的类型int,继而对模板进行一定的推演,判断出T的类型int,然后根据模板实例一个用int数据交换的函数。实际函数调用的不是模板,而是调用的是模板生成的代码。

其实函数一点也没有减少,只是有了模板编译器帮我们生成了。

T不明确

下面看这段代码会报错吗?

T Add(const T&amp; left, const T&amp; right)
{
	return left + right;
}

int main()
{
	int a1 = 10;
	double d1 = 10.11;
	Add(a1, d1);
	return 0;
}

答案是会报错,这是因为模板再推演实例化的时候出现了歧义,他不知道T的类型int还是double;

怎么办呢?
简单强制类型转换这是根据实参传递形参自动推演模板类型

Add(a1, (int)d1);
Add((double) a1, d1);

那除了强制类型转换还有没有别的方法呢?
显示实例

 Add<int>(a1, d1)
 Add<double>(a1, d1)

模板实例化的函数和普通函数

int Add(int left, int right)
{
	return left + right;
}

// 通用加法函数
template<class T>
T Add(T left, T right)
{
	return left + right;
}

请问能同时存在吗?
能!

编译器调用哪个函数?
编译有个原则调用谁的成本低就调用谁。很显然如果调用模板实例化的函数需要推演实例化这些东西,所以它会调用普通函数。

那如果非要调用模板实例化的函数呢?
显示实例化

编译器自己选择
其实编译器非常聪明,它会调用跟它更加匹配的那个函数。

类模板

类模板就是定义一个模板参数,整个类里面都可以用。

那现在问题来了,之前学习typedef不够用吗?
答案是不够,比如一个栈,

typedef int STDateType;
class Stack
{
private:
	STDateType* _a;
	size_t _top;
	size_t _capacity;
};
int main()
{
	Stack st;
	return 0;
}

现在我栈上既要存储int又要存储double数据就办不到了!

类模板写法

template<class T>
class Stack
{
public:
	Stack(int capaicty = 4)
	{
		_a = new T[capaicty];
		_top = 0;
		_capacity = capaicty;
	}

	~Stack()
	{
		delete[] _a;
		_capacity = _top = 0;
	}

private:
	T* _a;
	size_t _top;
	size_t _capacity;
};

类模板用法

怎么用呢?必须得显示实例化。

int main()
{
	Stack<int> st1; // int
	Stack<double> st2; // double
	return 0;
}

注意事项

1.模板的名字不能直接表示类型,加上模板参数才能表示类型

vector <int> v1;

2.类里面如果声明和定义分离怎么写?


class Vector
{
	~Vector();
};
template<class T>
Vector<T>::~Vector()//不能只指定类名,得指定类型
{
	delete[] _pData;
	_pData = nullptr;
	_size = _capacity = 0;
}

3.类模板声明和定义一定要放在同一个文件
如果声明和定义分离出现链接错误

原文地址:https://blog.csdn.net/weixin_68359117/article/details/134819862

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_49797.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注