前往小程序,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 删除。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
超全干货 | 软件测试岗技术笔试
一条Bug记录最基本应包含:编号、Bug所属模块、Bug描述、Bug级别、发现日期、发现人、修改日期、修改人、修改方法、回归结果等等;要有效的发现Bug需参考需求以及详细设计等前期文档设计出高效的测试用例,然后严格执行测试用例,对发现的问题要充分确认肯定,然后再向外发布如此才能提高提交Bug的质量。
红目香薰
2022/11/29
4930
软件测试 | 复习
软件是一种逻辑实体,而不是具体的物理实体,因而它具有抽象性。( √ ) 白盒测试侧重于程序结构,黑盒测试侧重于功能,其中白盒测试需要程序员参与,黑盒测试不需要 ( × ) 单元测试通常应该先进行“人工走查”,再以白盒法为主,辅以黑盒法进行动态测试。( √ ) 集成测试也叫做组装测试,通常在编码完成的基础上,将所有的程序模块进行有序的、递增的测试( × ) 系统测试应尽可能在实际运行使用环境下进行( √ ) 详细设计的目的是为软件结构图中的每一个模块确定使用的算法和块内数据结构,并用某种选定的表达工具给出清晰的描 述。 ( √ ) 测试人员在测试过程中发现一处问题,如果问题影响不大,而自己又可以修改,应立即将此问题正确修改,以加快、提高开发的 进程。( × ) 程序、需求规格说明、设计规格说明都是软件测试的对象( √ ) 第三方测试是在开发方与用户方的测试基础上进行的验证测试 ( × ) 数据流图和数据字典共同构成系统的逻辑模型。( √ ) 软件测试的目的是尽可能多的找出软件的缺陷。(√) Beta 测试是验收测试的一种。(√) 为了提高测试效率,应该取一切可能的输入数据作为测试数据。 ( × ) 发现错误多的程序模块,残留在模块中的错误也多。( √ ) 系统测试的目标是要找出软件在与系统其他部分协调工作时出现的所有故障( × ) 软件测试就是为了验证软件功能实现的是否正确,是否完成既定目标的活动,所以软件测试在软件工程的后期才开始具体的工 作。 ( × ) 功能测试是系统测试的主要内容,检查系统的功能、性能是否与需求规格说明相同。(√) 软件质量管理即QM由QA和QC构成,软件测试属于QC的核心工作内容。( √ ) 软件测试只能发现错误,但不能保证测试后的软件没有错误。(√ ) I18N测试是指对产品做出具有国际性的规划,而L10N测试则是指对软件做出符合本地需求更改工作。(√) 验收测试是由最终用户来实施的。(× ) 单元测试能发现约80%的软件缺陷。(√) 自底向上集成需要测试员编写驱动程序。(√) 负载测试是验证要检验的系统的能力最高能达到什么程度。(×) 测试人员要坚持原则,缺陷未修复完坚决不予通过。(×) 代码评审员一般由测试员担任。(×) 我们可以人为的使得软件不存在配置问题。(×) 系统测试是在需求分析阶段准备的。( √ ) 集成测试分为非增量式集成和增量式集成测试方式。 ( √ )
yiyun
2023/01/11
6570
软件测试 | 复习
软件测试常见面试题汇总
1. 一条软件缺陷(或者叫Bug)记录都包含了哪些内容? 如何提交高质量的软件缺陷(Bug)记录?
全栈程序员站长
2022/09/27
5620
软件项目版本号命名规则和项目文档命名规范
注:中括号内可选,如:1.0 ,1.2.1,5.0.0 build-13124 ,1.1.1.090520_beta。
孙小北
2024/01/30
2K0
程序员面试之软件测试面试问答
1、问:你在测试中发现了一个bug,但是开发经理认为这不是一个bug,你应该怎样解决? 首先,将问题提交到缺陷管理库里面进行备案。 然后,要获取判断的依据和标准: 根据需求说明书、产品说明、设计文档等,确认实际结果是否与计划有不一致的地方,提供缺陷是否确认的直接依据; 如果没有文档依据,可以根据类似软件的一般特性来说明是否存在不一致的地方,来确认是否是缺陷; 根据用户的一般使用习惯,来确认是否是缺陷; 与设计人员、开发人员和客户代表等相关人员探讨,确认是否是缺陷; 合理的论述,向测试
互联网金融打杂
2018/04/03
1.6K0
一篇文章了解软件测试基础知识
白盒测试:测试人员需要了解代码程序结构和处理过程,按照代码逻辑进行测试,比如接口测试。
孟船长
2019/04/28
1.6K0
一篇文章了解软件测试基础知识
软件测试与代码安全详解
本人学习软件测试收获不少,于是便记录下来自己的思路与知识总结,重温自己的探索之路。
达达前端
2019/07/03
5870
软件测试基本概念
根据用户需求行业规范,采用一些测试方法或一些工具对被测系统(程序数据文档)进行相应的测试(审核,运行,评估),尽早尽快的发现软件问题,提升软件的质量。
测试小兵
2019/09/03
6740
软件测试基础笔记
(1)单元测试 - 模块测试,检查每个程序单元能否正确实现详细设计说明中的模块功能等。
wangmcn
2022/10/30
3830
软件测试习题(附答案)
1. 在软件生命周期的哪一个阶段,软件缺陷修复费用最低                               (   A   )
红目香薰
2022/11/29
1.8K0
【测试】软件测试知识点-期中复习1
1.2简述软件测试V模型的流程 需求分析——概要设计——详细设计——编码——单元测试——集成测试——系统测试——验收测试
瑞新
2020/07/07
6090
【测试】软件测试知识点-期中复习1
如何系统自学软件测试,看这篇软件测试学习方法万字总结就够了
主要分享测试的学习资源,帮助快速了解测试行业,帮助想转行、进阶、小白成长为高级测试工程师。
伤心的辣条
2022/12/14
9720
如何系统自学软件测试,看这篇软件测试学习方法万字总结就够了
二十五个软件测试经典面试题,你确定不收藏一波?
1、在搜索引擎中输入汉字就可以解析到对应的域名,请问如何用LoadRunner进行测试?
新梦想IT职业教育
2019/09/12
1.1K0
软件测试:基础概念
软件测试是软件开发过程中至关重要的一环,它确保了软件的质量和稳定性。随着软件开发的快速发展,软件测试的重要性日益凸显。本文将深入探讨软件测试的艺术,帮助读者理解测试的原则、方法和技术,并掌握如何在实际项目中运用它们。
人不走空
2024/02/20
2120
相关推荐
超全干货 | 软件测试岗技术笔试
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验