前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【C++初阶】C++模板编程入门:探索泛型编程的奥秘

【C++初阶】C++模板编程入门:探索泛型编程的奥秘

作者头像
Eternity._
发布于 2024-06-14 11:43:39
发布于 2024-06-14 11:43:39
17800
代码可运行
举报
文章被收录于专栏:登神长阶登神长阶
运行总次数:0
代码可运行

前言:在C++编程世界中,模板是一个强大的工具,它使得程序员能够编写更加通用、灵活和可重用的代码。通过模板,我们可以编写与类型无关的代码,这些代码可以在编译时根据所需的具体类型进行实例化。本文将带你走进C++模板的初阶世界,探索泛型编程的基石

泛型编程: 编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。


📒1. 为什么需要模板?

我们来看看之前如何实现一个交换函数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 函数重载
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;
}
int main()
{
	int a = 1, b = 9;
	double c = 1.1, d = 8.9;
	char e = 'a', f = 'b';
	Swap(a, b); Swap(c, d); Swap(e, f);
	cout << a << " " << b << endl;
	cout << c << " " << d << endl;
	cout << e << " " << f << endl;
	return 0;
}

  • 我们虽然能用函数重载来解决这个问题,但是函数代码冗余
  • 仅仅是类型的不同,每当出现新类型时,就需要增加对应的函数
  • 代码的可维护性比较低,一个出错可能所有的重载均出错

在编程中,我们经常遇到需要处理不同类型数据的场景。为了处理这些类型,我们通常需要编写多个函数或类,每个函数或类都针对特定的数据类型进行实现。这不仅增加了代码的冗余度,也降低了代码的可维护性和可重用性。模板的引入就是为了解决这个问题。通过使用模板,我们可以编写与类型无关的代码,这些代码可以在编译时根据所需的具体类型进行实例化,从而生成针对特定类型的代码


📒2. 函数模板

🌈函数模板概念

根据上面的示例代码我们能够用模板修改

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template<typename T>
void Swap(T& left, T& right)
{
	 T temp = left;
	 left = right;
	 right = temp;
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
格式:template<typename T>  T 表示类型

template < typename T> 声明了一个模板参数T,它表示任意类型 。在函数参数和返回类型中,我们都使用了T,这样该函数就可以处理任何类型的数据了 有了这个函数就能实现上述三个交换函数

注意: typename是用来定义模板参数关键字,也可以使用class (切记:不能使用struct代替class)


🌈函数模板的原理

函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模板就是将本来应该我们做的重复的事情交给了编译器

在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于字符类型也是如此


🌈函数模板的实例化

用不同类型的参数使用函数模板时,称为函数模板的实例化 模板参数实例化分为:隐式实例化显式实例化


🌙隐式实例化

隐式实例化:让编译器根据实参推演模板参数的实际类型

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 隐式实例化
template<class T>
T Add(const T& left, const T& right)
{
	return left + right;
}
int main()
{
	int a1 = 10, a2 = 20;
	double d1 = 10.0, d2 = 20.0;
	Add(a1, a2);
	Add(d1, d2);
	// 在这里要注意一点,在模板中,编译器一般不会进行类型转换操作
	//Add(a1, d1); false
	// 虽然编译器不会进行类型转换,但是我们能自己来强制转化或者显式实例化
	Add(a1, (int)d1);
	return 0;
}

模板参数列表中只有一个T时,无法将两个类型不同的放在一起推演,编译器无法确定此处到底该将T确定什么类型而报错


🌞显式实例化

显式实例化:在函数名后的<>中指定模板参数的实际类型

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 显式实例化
template<class T>
T Add(const T& left, const T& right)
{
	return left + right;
}
int main()
{
	int a1 = 10, a2 = 20;
	double d1 = 10.0, d2 = 20.0;
	// 显式实例化
	Add<int>(a1, d1);
	return 0;
}

注意:

  • 如果类型不匹配,编译器会尝试进行隐式类型转换
  • 如果无法转换成功编译器将会报错

🌈模板参数的匹配原则

模板参数的匹配原则:

  • 🌹一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数
  • 🌸对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板
  • 🌻模板函数不允许自动类型转换,但普通函数可以进行自动类型转换
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 专门处理int的加法函数
int Add(int left, int right)
{
return left + right;
}
// 通用加法函数
template<class T>
T Add(T left, T right)
{
return left + right;
}
int main()
{
	Add(1314, 520); // 与非模板函数匹配,优先调用非模板函数
	Add<int>(1314.0, 520.0); // 调用编译器特化的Add版本
}

int Add能够和T Add同时存在,在调用函数时若参数和非模板函数匹配,那么编译器会优先调用非模板函数若非模板函数;不匹配或模板函数更匹配,那么编译器会优先调用模板函数


📒3. 类模板

类模板是对一批仅成员数据类型不同的类的抽象。通过为这一批类组成的类家族创建一个类模板,并提供一套程序代码,程序员可以生成多种具体的类,从而显著提高编程效率

🎈类模板的定义格式

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template<class T1, class T2, ..., class Tn>
class pxt//类模板名
{
	// 类内成员定义
};

我们来定义一个简单的顺序表

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template<class T>
class Vector
{
public:
	Vector(size_t capacity = 10)
		: _pData(new T[capacity])
		, _size(0)
		, _capacity(capacity)
	{}
	// 使用析构函数演示:在类中声明,在类外定义。
	~Vector();

	T& operator[](size_t pos)
	{
		assert(pos < _size);
		return _pData[pos];
	}
private:
	T* _pData;
	size_t _size;
	size_t _capacity;
};
// 注意:类模板中函数放在类外进行定义时,需要加模板参数列表
template <class T> //这里不要忘记带上
Vector<T>::~Vector()
{
	if (_pData)
		delete[] _pData;
	_size = _capacity = 0;
}

关于类模板其实就是将原来实际类型的位置变成T

🎩类模板的实例化

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

关于类模板的实例化必须显示实例化,类模板没有隐式推演

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// Vector类名,Vector<int>才是类型
Vector<int> v1;
Vector<double> v2;

🔥4. 总结拓展

拓展:🐫驼峰命名法

🐫驼峰命名法(CamelCase): 是电脑程序编写时常用的一套命名规则,通过混合使用大小写字母来构成变量、函数、类名等的名字。这种命名方式有助于提高代码的可读性和可维护性

驼峰命名法在多种编程语言中都有广泛应用,如Java、C#、JavaScript、Python等。在编写代码时,根据命名对象的类型(如变量、函数、类等)选择合适的驼峰命名法可以提高代码的可读性和可维护性!!!


🐼命名规则: 当变量名、函数名或类名由多个单词组成时,第一个单词以小写字母开始,从第二个单词开始以后的每个单词的首字母都采用大写字母。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 例如:
myFirstName
printEmployeePaychecks

🐋驼峰命名法的分类

🐟小驼峰法(lower camel case):

  • 命名规则:第一个单词首字母小写,后续单词首字母大写
  • 使用场景:常用于变量名、方法名、属性名
  • 示例:myStudentCount、getUserName()、userModel

🐬大驼峰法(upper camel case):

  • 命名规则:所有单词的首字母均大写。
  • 使用场景:常用于类名、接口名、常量名等。
  • 示例:DataBaseUser、UserService

🐷优点

  • 可读性好: 驼峰命名法通过大小写来区分单词,使得代码更容易阅读和理解
  • 易于书写和记忆: 采用统一的命名规则可以提高代码的一致性和可维护性
  • 符合编程语言的习惯: 通过明确的命名规则,可以减少变量、函数、类等名称之间的冲突

🐨注意事项

  • 在使用驼峰命名法时,需要注意单词之间的分隔,避免使用下划线或其他特殊字符
  • 对于类名、接口名等,建议使用大驼峰法,以突出其重要性
  • 在编写代码时,应保持命名的一致性,避免混用不同的命名方式

总之,驼峰命名法是一种简单、清晰、易读的命名方式,在程序编写中被广泛使用。通过合理使用驼峰命名法,可以提高代码的可读性和可维护性,降低编程错误率


总结: 在完成C++模板初阶的学习之后,我们可以深刻地感受到模板在C++编程中的强大与灵活性。模板作为C++编程语言的一个重要特性,为我们提供了一种在编译时生成特定类型代码的机制,从而实现了代码的重用和泛型编程。下节我们将进入C++ STL,对STL进行深入发掘 谢谢大家支持本篇到这里就结束了,祝大家天天开心!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-06-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【C++】模板初阶:泛型编程的起点
泛型编程是一种编程范式,它允许在编写代码时使用一种通用的数据类型或算法,以便在不同的数据类型上进行操作,而不需要为每种数据类型编写专门的代码。泛型编程的目标是提高代码的重用性和可扩展性。
大耳朵土土垚
2024/05/06
1710
【C++】模板初阶:泛型编程的起点
C++初阶-模板初阶
C++模板初阶 零、前言 一、泛型编程 二、函数模板 1、函数模板定义及使用 2、函数模板原理 3、函数模板实例化 4、函数模板匹配原则 三、类模板 1、类模板定义及使用 2、类模板实例化 零、前言 本章主要讲解C++的模板相关的初阶知识 一、泛型编程 用函数重载来实现交换变量函数: void Swap(int& left, int& right) { int temp = left; left = right; right = temp; } void Swap(double& left, d
用户9645905
2022/11/30
4580
C++初阶-模板初阶
C++模板(初阶)
如果我们定义了这个函数,其参数是int&类型的,也就是只能将整型的数据进行交换,那么如果我一个项目里面,不仅要进行整型的数据交换,还要浮点,自定义类型等等,那岂不是要使用很多个函数,而且函数的内容几乎一样。
二肥是只大懒蓝猫
2023/03/30
4030
C++模板(初阶)
【C++】模板初阶
函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。
六点半就起.
2024/10/16
990
【C++】模板初阶
【C++】泛型编程——模板初阶
C++引入了泛型编程,就可以解决这个问题。 泛型编程:编写与类型无关的通用代码,是代码复用的一种手段。 模板是泛型编程的基础,又分为函数模板和类模板。
YIN_尹
2024/01/23
1780
【C++】泛型编程——模板初阶
【C++】初识模板,拿来吧你
文章目录 一、泛型编程 二、函数模板 1.函数模板概念 2.函数模板格式 3.函数模板的原理 4 函数模板的实例化 1. 隐式实例化 2. 显式实例化 5.模板参数的匹配原则 三、类模板 1 类模板的定义格式 2 类模板的实例化 四、模板不支持分离编译(了解) 一、泛型编程 如何实现一个通用的交换函数呢? 我们可以针对不同的数据类型写出不同的交换函数 void Swap(int& left, int& right) { int temp = left; left = right;
平凡的人1
2022/11/15
2820
【C++】初识模板,拿来吧你
C++底层学习预备:模板初阶
定义一个Shape基类,包含计算面积的纯虚函数,再派生出Circle和Rectangle等类,重写计算面积的函数,体现了面向对象的继承和多态特性
DARLING Zero two
2025/02/04
690
C++底层学习预备:模板初阶
C++从入门到精通——模板
C++模板是C++语言中的一种泛型编程技术,可以实现在编译期间生成不同类型的函数或类。通过使用模板,可以编写通用的代码,使其能够处理多种不同类型的数据。
鲜于言悠
2024/04/24
1410
C++从入门到精通——模板
模板初阶介绍
1. 重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函数
用户11039545
2024/08/17
870
模板初阶介绍
C++中的标准化工厂—— 模板
        众所周知,C++是基于C语言的编写,所以它也继承了众多C的特性(当然也包括部分缺点),且基于它们进行改良和优化,这篇文章要讲的是模板,这算的上是C++基于C的一个“懒人利器”
比特大冒险
2023/04/16
8000
C++中的标准化工厂—— 模板
C++初阶:入门泛型编程(函数模板和类模板)
现在就轮到泛型编程出场了:编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。
是Nero哦
2024/02/01
2630
C++初阶:入门泛型编程(函数模板和类模板)
C++之模板(上)
本文介绍了C++模板的基础概念,简单介绍了泛型编程,模板,以及模板中的函数模板与类模板等相关概念。
摘星
2023/04/28
4300
C++之模板(上)
【C++】模板初阶
以实现交换函数为例,在C语言中即使是近乎完全一致的的功能,通过代码实现,只要参数不同,我们就需要写对应类型的不同函数名的函数,在之前的学习中,我们已经学习了函数重载,我们不再需要起不同的函数名,比起C语言方便不少,但是不容忽视的是函数重载仍然有不好的地方。
ZLRRLZ
2024/12/13
990
【C++】模板初阶
初识C++模板
        在写代码时,我们常常因为一个函数的类型不同而不能使用感到困扰。一个简单的交换函数,我们可能都得写好几份
青衫哥
2023/03/31
4230
初识C++模板
【C++】格式与实例化操作——[模板]详解(初级)(7)
PS:typename是用来定义模板参数关键字,也可以使用class(切记:不能使用struct代替class)
YY的秘密代码小屋
2024/01/22
1260
【C++】格式与实例化操作——[模板]详解(初级)(7)
C++-模板基础
大家在学习过程中一定写过swap函数吧,那么swap函数的可以写成很多种形式,因为形参的类型可以是任意类型,那么我们如果想用多种swap函数的话,就意味着我们必须写多个swap函数吗?不是的,C++为了解决这个问题,引入了模板这个概念。
用户10923087
2024/02/05
1200
C++-模板基础
C++:模版初阶 | STL简介
使用函数重载虽然可以实现,但是有一下几个不好的地方: 1. 重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函数 2. 代码的可维护性比较低,一个出错可能所有的重载均出错
小陈在拼命
2024/03/01
1690
C++:模版初阶 | STL简介
【C++篇】引领C++模板初体验:泛型编程的力量与妙用
通过阅读本文,你将能够掌握C++模板编程的基础知识,理解其背后的工作原理,并学会如何在实际项目中应用这些技术。
半截诗
2024/10/09
2720
【C++篇】引领C++模板初体验:泛型编程的力量与妙用
初识模板及其STL
如果在C++中,存在一个摸具,通过给这个摸具中填充不同材料(类型),赖获得不同材料的锻件(即生成具体类型的代码),那么就会节省许多头发。对此C++提出模板的概念,对于模板分为函数模板以及类模板。
是店小二呀
2024/08/13
1220
初识模板及其STL
【泛型编程】模板全详解
在c语言中,如果我们想写多类型的,并且是同一个函数出来的函数,我们只能要几个写几个出来,这样子会显得比较冗余,也加大了程序员的代码量,于是c++中就引入了函数重载和泛型编程的概念,大大的简化了我们的工作!
利刃大大
2023/04/12
7130
【泛型编程】模板全详解
相关推荐
【C++】模板初阶:泛型编程的起点
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验