模板初阶(泛型编程)

news/2024/11/30 7:36:39/

在这里插入图片描述

模板初阶

  • 🔆泛型编程
  • 🔆函数模板
    • 函数模板概念
    • 函数模板格式
    • 函数模板的原理
    • 函数模板的实例化
    • 模板参数的匹配原则
  • 🔆类模板
    • 类模板的定义格式
    • 类模板的实例化
    • 类模板与模板类的区别
  • 🔆结语

🔆泛型编程

泛型编程:编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。
在这里插入图片描述

🔆函数模板

函数模板概念

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

函数模板格式

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

template<typename T>
void Swap(T& n1, T& n2) {T tmp = n1;n1 = n2;n2 = tmp;
}

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

函数模板的原理

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

函数模板的实例化

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

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

template<typename T>
T Add(const T& a, const T& b) {return (a + b);
}int main() {int a = 1;int b = 2;float c = 3.3f;float d = 4.4f;Add(a, b);Add(c, d);//Add(a, c);  //这里编译器会报错,模板参数只有一个,而这里有两种类型的实参,编译器无法确定此处该转换为哪种类型,编译报错//解决办法:1.强制转换;2.显示实例化Add(a, (int)c);Add<int>(a, c);return 0;
}

2.显示实例化:在调用函数时,在函数名后的<>中指定模板参数的实际类型。

template<typename T>
T Add(const T& a, const T& b) {return (a + b);
}int main() {int a = 1;double b = 6.6;Add<double>(a,b);return 0;
}

模板参数的匹配原则

1. 一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数

int Add(const int& a, const int& b) {cout << "int Add(const int& a, const int& b)" << endl;return a + b;
}template<typename T>
T Add(const T& a, const T& b) {cout << "T Add(const T& a, const T& b)" << endl;return a + b;
}int main() {Add(1, 2);  //与非模板函数匹配,编译器不需要转换Add<int>(1, 2);  //调用编译器使用函数模板生成的Addreturn 0;
}

在这里插入图片描述

2.对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板

int Add(const int& a, const int& b) {cout << "int Add(const int& a, const int& b)" << endl;return a + b;
}template<typename T1, typename T2>
T1 Add(const T1& a, const T2& b) {cout << "T1 Add(const T1& a, const T2& b)" << endl;return a + b;
}int main() {Add(1, 2);   //编译器调用非函数模板的同名函数Add(1, 2.0); //函数模板可以实例化出更匹配的版本,编译器根据实参生成更加匹配的Add函数return 0;
}

在这里插入图片描述

3.模板函数不允许自动类型转换,但普通函数可以进行自动类型转换

//这个函数可以自动类型转换
int Add(const int& a, const int& b) {cout << "int Add(const int& a, const int& b)" << endl;return a + b;
}//这个函数模板实例化不出来类型不同的函数,不可以自动类型转换
//template<typename T>
//T Add(const T& a, const T& b) {
//	cout << "T1 Add(const T1& a, const T2& b)" << endl;
//	return a + b;
//}int main() {Add(1, 2.0);return 0;
}

🔆类模板

类模板的定义格式

template<class T1, ......, class Tn>
class {//类内成员的定义
};
template<class T>
class Stack{
public:Stack(const int capacity = 4);~Stack();
private:T* _a;int _top;int _capacity;static int _b;
};template<class T>
int Stack<T>::_b = 0;//注意类模板在类外定义成员函数时,需要加模板参数列表
template<class T>
Stack<T>::Stack(const int capacity):_a(new T[4]{ 0 }),_top(-1),_capacity(capacity)
{}template<class T>
Stack<T>::~Stack() {delete[] _a;_top = -1;_capacity = 0;
}

类模板的实例化

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

template<class T>
class Stack{
public:Stack(const int capacity = 4);~Stack();
private:T* _a;int _top;int _capacity;static int _b;
};template<class T>
int Stack<T>::_b = 0;//注意类模板在类外定义成员函数时,需要加模板参数列表
template<class T>
Stack<T>::Stack(const int capacity):_a(new T[4]{ 0 }),_top(-1),_capacity(capacity)
{}template<class T>
Stack<T>::~Stack() {delete[] _a;_top = -1;_capacity = 0;
}int main() {//Stack是类名,Stack<int>才是s的类型Stack<int> s;return 0;
}

类模板与模板类的区别

类模板:主要描述的是模板,这个模板是类的模板。可以理解为一个通用的类,这个类中的数据成员,成员函数的形参类型以及成员函数的返回值类型不用具体的指定,这些类型都是虚拟的。在使用类模板进行对象定义的时候,才会根据对象的实际参数类型来替代类模板中的虚拟类型。通俗一点来说,可以看作是做蛋糕的模具。
模板类:主要描述的是类,这个类使用类模板进行声明。将类模板中的虚拟类型参数指定成一个具体的数据类型参数。通俗一点来说可以看作是通过蛋糕模具做出来的蛋糕。

int main() {//Stack是模板类//s是模板类Stack<int> s;return 0;
}

🔆结语

到这里这篇博客已经结束啦。
这份博客👍如果对你有帮助,给博主一个免费的点赞以示鼓励欢迎各位🔎点赞👍评论收藏⭐️,谢谢!!!
如果有什么疑问或不同的见解,欢迎评论区留言欧👀


http://www.ppmy.cn/news/71977.html

相关文章

【数据库】存储过程

存储过程/函数:procedure/function 通俗说,存储过程是个模块化的程序段,完成一定功能,可被反复调用,可用于解决复杂的问题,减少程序冗余度。 这里的过程和函数就是C语言的方法/函数。过程一般不直接返回值,但可以通过实参和形参返回给主调程序计算结果;函数在SQLSERV…

Py基础可视化-Matplotlib Seaborn总结篇

那么Py基础可视化暂时告一段落&#xff0c;回顾主要分两个内容&#xff1a;Matplotlib 绘图底层参数设置 &Seaborn 基础图的的绘制。 Python 可视化 1 Matplotlib-图像结果及绘图设置 2 Matplotlib-坐标轴&刻度值&刻度&标题设置 3 Matplotlib-seborn 图形…

【漏洞预警】泛微E-Cology ofsLogin任意用户登陆漏洞

泛微ofsLogin任意用户登陆漏洞 漏洞描述 泛微e-cology是一套兼具企业信息门户、知识文档管理、工作流程管理、人力资源管理、客户关系管理、项目管理、财务管理、资产管理、供应链管理、数据中心功能的企业大型协同管理平台。 泛微e-cology前台任意用户登录漏洞&#xff1a;…

Redis系列--主从复制

一、redis主从复制介绍 在 Redis 复制的基础上&#xff0c;使用和配置主从复制非常简单&#xff0c;能使得从 Redis 服务器&#xff08;下文称 slave&#xff09;能精确得复制主 Redis 服务器&#xff08;下文称 master&#xff09;的内容。每次当 slave 和 master 之间的连接断…

含sop的配电网重构(含风光|可多时段拓展)

目录 1 主要内容 2 部分程序 3 下载链接 1 主要内容 之前分享了很多配电网重构的程序&#xff0c;每个程序针对场景限定性比较大&#xff0c;程序初学者修改起来难度较大&#xff0c;本次分享一个基础程序&#xff0c;针对含sop的配电网重构模型&#xff0c;含风电和光伏&…

简单分享线程池的设计

温故而知新&#xff0c;可以为师矣。 线程池是什么 线程池&#xff08;Thread Pool&#xff09;是一种基于池化思想管理线程的工具&#xff0c;经常出现在多线程服务器中&#xff0c;如MySQL。 池化思想&#xff0c;就是为了提高对资源的利用率&#xff0c;减少对资源的管理&a…

【黑马2023大数据实战教程】VMWare虚拟机部署HDFS集群详细过程

文章目录 部署HDFS集群1.配置workers:2.配置hadoop-env.sh文件3.配置core-site.xml文件4.配置hdfs-site.xml文件准备数据目录分发Hadoop文件夹配置环境变量授权为hadoop用户格式化文件系统错误排查方法!! 视频&#xff1a;黑马2023 VMWare虚拟机部署HDFS集群 注意&#xff01;这…