【C++】——模板(泛型编程+函数模板+类模板)

这篇具有很好参考价值的文章主要介绍了【C++】——模板(泛型编程+函数模板+类模板)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 前言

之前我们学习了函数重载,让我们在写相似函数的时候非常方便,但函数重载还有很多不足的地方,比如,每次写相似函数的时候,都要我们重新重载一个逻辑、代码几乎一样的函数,这就导致了我们的效率变低,所以我们今天来学习C++模板的相关知识点,学习完模板之后,我们就可以很好的解决这些问题。

2. 泛型编程

以前我们要实现一个通用的交换函数时是怎么做的呢?我们利用了函数重载,把可能用到的函数都重载出来。

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;
}

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

使用函数重载虽然可以做到,但是有几个不足的地方:

1.重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函数
2.代码的可维护性比较低,一个出错可能所有的重载均出错

那么我们该如何解决这个问题呢?
如果在C++中,能够存在一个模具,通过给这个模具中填充不同材料(类型),来获得不同材料的铸件(即生成具体类型的代码)这样就会让我们大幅提高效率。

泛型编程
编写与类型无关的通用代码,是代码复用的一种手段。
模板是泛型编程的基础。模板又分为函数模板和类模板。

3. 函数模板

概念
函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。
格式
template<typename T1, typename T2,…,typename Tn>
返回值类型 函数名(参数列表) {}
注意
typename是用来定义模板参数关键字,也可以使用class。
typename后面类型名字T是随便取的。

//template<typename T>
template<class T>
void Swap(T& left, T& right)
{
	T tmp = left;
	left = right;
	right = tmp;
}

3.1 函数模板的原理

函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模板就是将本来应该我们做的重复的事情交给了编译器。
在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。
比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于字符类型也是如此。

3.2 函数模板的实例化

用不同类型的参数使用函数模板时,称为函数模板的实例化。模板参数实例化分为:隐式实例化和显式实例化。
隐式实例化:让编译器根据实参推演模板参数的实际类型
显式实例化:在函数名后的<>中指定模板参数的实际类型

template<typename T>
T Add(const T& x, const T& y)
{
	return x + y;
}

int main()
{
	int a = 1, b = 2;
	double c = 1.1, d = 2.2;

	//编译器自动推演,隐式实例化
	cout << Add(a, b) << endl;
	cout << Add(c, d) << endl;

	//推演实例化矛盾,编译器无法确定此处到底该将T确定为int或者double类型而报错
	//cout << Add(a, d) << endl;

	//俩种处理方式:1、强制转换类型   2、显示实例化
	//1.强制转换类型
	cout << Add((double)a, d) << endl;
	cout << Add(a, (int)d) << endl;

	//2.显示实例化
	cout << Add<double>(a, d) << endl;
	cout << Add<int>(a, d) << endl;

	return 0;
}

【C++】——模板(泛型编程+函数模板+类模板)

3.3 模板参数的匹配原则

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

//专门处理加法的函数
int Add(const int& x, const int& y)
{
	return x + y;
}

//通用加法函数
template<class T>
T Add(const T& x, const T& y)
{
	return x + y;
}

template<class T1, class T2>
T2 Add(const T1& x, const T2& y)
{
	return x + y;
}

int main()
{
	cout << Add(1, 2) << endl;//调用int Add函数
	cout << Add(1.1, 2.2) << endl;//调用T Add函数
	cout << Add(1, 2.2) << endl;//调用T2 Add函数

	return 0;
}

4. 类模板

格式
template<class T1, class T2, …, class Tn>
class 类模板名
{
// 类内成员定义
};

template<class T>
class Stack
{
public:
	Stack(size_t capacity = 4)
		:_a(nullptr)
		,_top(0)
		,_capacity(0)
	{
		if (capacity > 0)
		{
			_a = new T[capacity];
			_capacity = capacity;
			_top = 0;
		}
	}

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

	void Push(const T& x)
	{}
	//注意:类模板中函数放在类外进行定义时,需要加模板参数列表

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

注意:类模板中函数放在类外进行定义时,需要加模板参数列表

4.1 类模板的实例化

类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。

template<class T>
class Stack//这里Stack不是具体的类,是编译器根据被实例化的类型生成具体类的模具
{
public:
	Stack(size_t capacity = 4)
		:_a(nullptr)
		,_top(0)
		,_capacity(0)
	{
		if (capacity > 0)
		{
			_a = new T[capacity];
			_capacity = capacity;
			_top = 0;
		}
	}

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

	void Push(const T& x)
	{}

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

int main()
{
	//类模板都是显示实例化
	//虽然他们用了一个类模板,但是Stack<int>,Stack<char>是两个类型
	Stack<int> st1;
	Stack<char> st2;
	
	//知道要存多少个数据,避免插入时扩容消耗
	Stack<int> st3(100);

	return 0;
}

注意
1.类模板必须显示实例化。
2.虽然上面两个对象用了同一个类模板,但是Stack<int>,Stack<char>是两个不同的类型。

5. 结尾

C++模板入门的相关知识点我们就学习完了,学了模板以后,在很多地方我们就可以用模板来实现,而不是重载函数,这能极大的提高效率和可维护性。
最后,感谢各位大佬的耐心阅读和支持,觉得本篇文章写的不错的朋友可以三连关注支持一波,如果有什么问题或者本文有错误的地方大家可以私信我,也可以在评论区留言讨论,再次感谢各位。文章来源地址https://www.toymoban.com/news/detail-453830.html

到了这里,关于【C++】——模板(泛型编程+函数模板+类模板)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C++】泛型编程 ① ( 函数模板 | 函数模板概念 | 函数模板意义 | 函数模板定义语法 | 函数模板调用语法 | 显式类型调用 | 自动类型推导 )

    在 C++ 语言中 , 泛型编程 的 核心就是 函数模板 和 类模板 ; 函数模板 Function Template 是 C++ 语言 中的 重要特性 ; 函数模板概念 : 建立一个 \\\" 通用函数 \\\" , 不指定该函数的 函数返回值类型 和 函数参数类型 , 仅使用 \\\" 虚拟类型 \\\" 代表 上述 两种类型 , 该 \\\" 通用函数 \\\" 就是 \\\" 函数模

    2024年02月19日
    浏览(28)
  • C++、STL标准模板库和泛型编程 ——迭代器、 算法、仿函数(侯捷)

    侯捷 C++八部曲笔记汇总 - - - 持续更新 ! ! ! 一、C++ 面向对象高级开发 1、C++面向对象高级编程(上) 2、C++面向对象高级编程(下) 二、STL 标准库和泛型编程 1、分配器、序列式容器 2、关联式容器 3、迭代器、 算法、仿函数 4、适配器、补充 三、C++ 设计模式 四、C++ 新标准 五、

    2023年04月25日
    浏览(38)
  • 【C++】泛型编程——模板进阶

    在之前的文章里,我们进行了模板初阶的学习( 【C++】泛型编程——模板初阶),了解了什么是泛型编程,学习了函数模板和类模板。 那这篇文章,我们继续学习模板进阶的内容的学习。 首先我们来回顾一下: 我们在模板初阶的学习中,定义模板参数是怎么定义的? 是不

    2024年02月16日
    浏览(27)
  • C++泛型编程之模板

    目录 一、什么是泛型编程  二、函数模板 2.1函数模板的概念 2.2函数模板格式 2.3函数模板的原理  2.5函数模板的实例化 2.6模板参数的匹配原则 三、类模板 3.1类模板的定义格式 3.2 类模板的实例化 四、非类型模板参数 五、模板的特化 5.1模板特化的概念: 5.2函数模板特化 5

    2024年02月07日
    浏览(29)
  • 【C++】C++泛型编程 | 模板初阶

      🧑‍🎓 个人主页:简 料   🏆 所属专栏:C++   🏆 个人社区:越努力越幸运社区   🏆 简       介: 简料简料,简单有料~在校大学生一枚,专注C/C++/GO的干货分享,立志成为您的好帮手 ~ C/C++学习路线 (点击解锁) ❤️ C语言 ❤️ 初阶数据结构与算法 ❤️ C++ ❤️

    2024年02月08日
    浏览(65)
  • 【C++基础(十)】C++泛型编程--模板初阶

    💓博主CSDN主页:杭电码农-NEO💓   ⏩专栏分类:C++从入门到精通⏪   🚚代码仓库:NEO的学习日记🚚   🌹关注我🫵带你学习C++   🔝🔝 在学习数据结构时会遇见以下的情况 数据结构中存储的类型往往不能确定 所以在实现数据结构时往往是这样做的 在写代码时用DateType来表

    2024年02月13日
    浏览(22)
  • C++——模板初阶与泛型编程

    🌸作者简介: 花想云 ,在读本科生一枚,致力于 C/C++、Linux 学习。 🌸 本文收录于 C++系列 ,本专栏主要内容为 C++ 初阶、C++ 进阶、STL 详解等,专为大学生打造全套 C++ 学习教程,持续更新! 🌸 相关专栏推荐: C语言初阶系列 、 C语言进阶系列 、 数据结构与算法 本章我们

    2023年04月17日
    浏览(30)
  • 【c++ primer 笔记】第 16章 模板与泛型编程

    🎉作者简介:👓 博主在读机器人研究生,目前研一。对计算机后端感兴趣,喜欢 c + + , g o , p y t h o n , 目前熟悉 c + + , g o 语言,数据库,网络编程,了解分布式等相关内容 textcolor{orange}{博主在读机器人研究生,目前研一。对计算机后端感兴趣,喜欢c++,go,python,目前熟悉c+

    2024年02月20日
    浏览(28)
  • C++、STL标准模板库和泛型编程 ——适配器、补充(侯捷)

    侯捷 C++八部曲笔记汇总 - - - 持续更新 ! ! ! 一、C++ 面向对象高级开发 1、C++面向对象高级编程(上) 2、C++面向对象高级编程(下) 二、STL 标准库和泛型编程 1、分配器、序列式容器 2、关联式容器 3、迭代器、 算法、仿函数 4、适配器、补充 三、C++ 设计模式 四、C++ 新标准 五、

    2023年04月27日
    浏览(60)
  • C++核心编程——详解函数模板

    纵有疾风起,人生不言弃。本文篇幅较长,如有错误请不吝赐教,感谢支持。 ①为什么有模板? 在C++程序中,声明变量、函数、对象等实体时,程序设计者需要指定数据类型,让编译器在程序运行之前进行类型检查并分配内存,以提高程序运行的安全性和效率。 但是这种强

    2024年02月09日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包