C++_模板

       

目录

1、函数模板

1.2 模板原理

2、多个模板参数

3、模板的显示实例化

4、模板的匹配

5、类模板

结语:


前言:

        在C++中,模板分为函数模板和类模板,而模板的作用就是避免了重复的工作,把原本是程序员要做的重复工作交给了编译器去做。比如实现两个变量的交换函数,如果这两个变量是int类型则需要写一个int类型的交换函数,若是double类型则要再写一个double类型的交换函数,这样一来增加了很多反复的工作,若用函数模板就能解决以上问题,只需要写一个交换函数的模板,不管是什么类型,都可以通过该模板实现两个变量的交换。

1、函数模板

        用交换函数举例子,如果要交换三种类型的数据则需要三个交换函数构造重载,写起来很冗杂而且可读性较差:

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

        以上三个交换函数可以用一个函数模板代替,模板的格式如下:

template<class T1, class T2,......,class Tn>
//template是关键字,用于定义一个模板
//class替换成typyname也可以实现模板
//T1和T2是模板的关键部分,表示模板类型,可以接收任意的实参类型
//T1和T2也理解为模板参数

        有了模板的格式,就可以写一个交换函数的模板,同时测试交换各种不同的数据类型,观察利用函数模板是否可以实现交换。测试代码如下:

#include<iostream>
using namespace std;template<class T>//写在函数上面实现函数模板
void Swap(T& t1, T& t2)//Swap为函数模板名
{T temp = t1;t1 = t2;t2 = temp;
}int main()
{int a = 2, b = 3;double a1 = 2.2, b1 = 3.3;char a2 = 'a', b2 = 'b';Swap(a, b);Swap(a1, b1);Swap(a2, b2);cout << a << " " << b << endl;cout << a1 << " " << b1 << endl;cout << a2 << " " << b2 << endl;return 0;
}

        运行结果:


        这里要说明一点,模板的格式只对在他下面的第一个对象(即函数)有效,模板下面的第二个函数不是模板函数,比如:

1.2 模板原理

        模板表面上减少了很多重复的工作,实际上是把原本由程序员进行的重复工作交给了编译器完成,在底层,编译器还是会根据不同的类型去生成该类型的交换函数。

2、多个模板参数

        上述的模板参数只有一个,即:T。因为交换函数一般交换的两个变量类型都是相同的,因此一个模板参数就足够了,但是很多情况下函数要处理的数据类型不止一个,这时候该类情况的函数模板就需要多个模板参数了。

        多个模板参数写法如下:

#include<iostream>
using namespace std;template<class T1, class T2>//两个模板参数T1和T2
T1 func(T1& t1, T2& t2)//注意返回类型的选取
{return t1 + t2;
}int main()
{int a = 2;double b = 2.2;cout << func(a, b) << endl;
}

        运行结果:

        如果模板涉及到返回类型,则要注意返回类型的选取。 

3、模板的显示实例化

        以上模板参数的具体类型都是自动的根据实参类型而定的,把这种自动识别类型的方式叫做隐式实例化,除了隐式实例化识别模板参数类型,还可以手动指定模板参数类型,即在调用模板函数时,在函数名后面加上'<>',并且在‘<>’中写上指定的类型。

        如果只有一个模板参数是无法处理实参传递两个不同类型变量的情况,解决方法有两种:1、采用多个模板参数,2、使用显示实例化模板。

        显示实例化示例代码如下:

#include<iostream>
using namespace std;template <class T>
T Add(const T& t1,const T& t2)
{return t1 + t2;
}int main()
{int a = 2, b = 3;double a1 = 2.2, b1 = 3.3;//b1是double类型,a是int类型,而模板参数只有一个T,不能够直接的将a、b作为实参传递//因此可以手动指定模板参数T的类型为int,即显示实例化cout << Add<int>(a, b1) << endl;cout << Add<double>(a1, b) << endl;//double类型同理return 0;
}

        运行结果:

4、模板的匹配

        如果存在一个函数模板和一个非模板且同名的函数,调用时实参类型若与非模板且同名的函数的类型对应上,则直接调用非模板且同名的函数。若调用时实参类型必须要经过函数模板才能生成该类型的函数,则调用函数模板。总而言之就是编译器会自动调用“当下最匹配”的函数

        示例代码如下:

#include<iostream>
using namespace std;template <class T>
T Add(T t1, T t2)
{return t1 + t2;
}int Add(int x, int y)
{return x + y;
}int main()
{int a = 2, b = 3;Add(a, b);//此处调用int返回类型的AddAdd<int>(a, b);//若用显示调用则强制调用函数模板Adddouble a1 = 2.2, b1 = 3.3;Add(a1,b1);//只能通过调用模板函数Add来实现double类型的和Add(2, 2.2);//一个int类型,一个double类型,显然一个模板参数不够,因此会调用int类型Addreturn 0;
}

        示意图:

5、类模板

        之前通常都是用typedef进行类型的重命名,虽然该方法可以解决一部分问题,但是如果想让一个类实例化出两个不同类型的对象那么typedef就做不到了,只能通过显示实例化类模板,才能实现一个类可以实例化出两个不同类型的对象。

        类模板的格式跟函数模板相似,只不过把函数替换成了类:

template<class T1, class T2,......,class Tn>
class A//A表示类模板名
{}

        示例代码如下:

#include<iostream>
using namespace std;template<class T>
class Stack//Stack不再是具体的某一个类,而是一个类模板
{
public:Stack(int capacity=4)//构造函数初始化:_arr(new T[capacity])//可以申请不同类型的空间,_top(0),_capacity(capacity){}void push(const T& x)//压栈{_arr[_top++] = x;}T& operator[](int i)//显示栈里元素{return _arr[i];}private:T* _arr;//_arr可以转变不同类型的指针size_t _top;size_t _capacity;
};int main()
{Stack<int> sti;//Stack不再是类型,Stack<int>才是类型。Stack<double> std;//同理Stack<double>才是一个类型//可以同时实现两个数据类型的Stacksti.push(6);std.push(6.6);cout << sti[0] << endl;cout << std[0] << endl;return 0;
}

        运行结果:

        这里要注意的是:如果要通过类模板进行实例化对象,那么必须在类模板名的后面加上'<>',并且在‘<>’中表示类型,才能用类模板实例化对象。可以理解为类模板不是一个真正的类,而类模板+'<type>'才是一个真正的类。 

结语:

        以上就是关于C++模板的讲解,模板的出现减轻了程序员的工作,并且提供了代码的可读性和可维护性。最后希望本文可以给你带来更多的收获,如果本文对你起到了帮助,希望可以动动小指头帮忙点赞👍+关注😎+收藏👌!如果有遗漏或者有误的地方欢迎大家在评论区补充,谢谢大家!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/321140.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决docker容器内无法连接宿主redis

背景 小程序的发短信服务挂了&#xff0c;随查看日志&#xff0c;该报错日志如下 Error 111 connecting to 127.0.0.1:6379. Connection refused. 6379是监听redis服务的端口&#xff0c;那大概是redis出错了。 首先查看了redis是否正常启动&#xff0c;检查出服务正常。 由于小…

C# WinForm MessageBox自定义按键文本 COM组件版

c# 更改弹窗MessageBox按钮文字_c# messagebox.show 字体-CSDN博客 需要用到大佬上传到百度云盘的Hook类&#xff0c;在大佬给的例子的基础上改动了点。 应用时自己加GUID和ProgID。 组件实现&#xff1a; using System; using System.Collections.Generic; using System.L…

Python计算圆的面积

Python 计算圆的面积 圆的面积公式为 &#xff1a; 公式中 r 为圆的半径。 # 定义一个方法来计算圆的面积 def findArea(r): PI 3.142 return PI * (r*r) # 调用方法 r float( input("请输入圆的半径:") ) print( "圆的面积为 %.3f&qu…

C 练习实例16 - 最大公约数和最小公倍数

题目&#xff1a;输入两个正整数a和b&#xff0c;求其最大公约数和最小公倍数 数学&#xff1a;最大公约数*最小公倍数a*b 例如&#xff1a;a16&#xff0c;b20。最小公倍数80&#xff0c;最大公约数4。80*416*20。 算法&#xff1a;辗转相除法&#xff0c;又称欧几里德算法…

【LeetCode-剑指offer】-- 23.相交链表

23.相交链表 方法一&#xff1a;哈希集合 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) {* val x;* next null;* }* }*/ public class Solution {public ListNode getIn…

vue3中标签form插件

想写一个系统&#xff0c;对八字进行标注&#xff0c;比如格局&#xff0c;有些八字就有很多格局&#xff0c;于是就想着使用el-tag但是&#xff0c;form表单中如何处理呢&#xff1f; 这个时候&#xff0c;就需要自己写一个,modelValue是表单的默认属性 <template><…

Mysql事务transaction简介

文章目录 什么是事务针对Mysql隔离级别读未提交读提交可重复读串行化 mysql中的数据结构索引数据结构mysql中的锁种类**共享锁和独占锁**表锁、行锁(记录锁、间隙锁、临键锁) spring中的事务事务特性 什么是事务 事务是一个不可分割的数据库操作序列&#xff0c;也是数据库并发…

顶顶通呼叫中心中间件配置背景音乐(mod_cti基于FreeSWITCH)

介绍 配置外呼任务拨打时的背景音乐&#xff0c;一步步配置 一、配置队列外呼模板 打开ccadmin->队列呼叫模板->添加一条变量根据下方图片配置 二、上传音乐文件 后缀格式为.wav格式的声音文件&#xff0c;声音文件需要上传在这个目录&#xff1a;/ddt/fs/sounds/ct…

笔记——C语言基础讲义(黑马程序员)

1. C 语言概述 1.1 什么是 C 语言 一提到语言这个词语&#xff0c;自然会想到的是像英语、汉语等这样的自然语言&#xff0c;因为它是人和人交换信息不可缺少的工具。 而今天计算机遍布了我们生活的每一个角落&#xff0c;除了人和人的相互交流之外&#xff0c;我们必…

osg-材质 (osg::Material)

1.材质类 材质类 (osg::Material)继承自osg::StateAttribute 类。osg::Material 封装了 OpenGL的 glMaterial()和glColorMaterial()指令的函数功能&#xff0c;其继承关系图如图5-27 所示。 图 5-27 osg::Material 的继承关系图 在场景中设置节点的材质属性&#xff0c;首先要…

大数据计算基础真题回忆

转载学长20 21的真题 转载链接 注&#xff1a;每年的课件可能会有更改&#xff0c;内容不一样&#xff0c;所以读者复习的时候以所在年份的课件为准 2020 ​ 2021 笔者2023秋 2023 都是大题&#xff0c;没有选择题。 改进的近似算法中&#xff0c;结合具体的例子说明&am…

Java重修第一天—学习数组

1. 认识数组 建议1.5倍速学习&#xff0c;并且关闭弹幕。 数组的定义&#xff1a;数组是一个容器&#xff0c;用来存储一批同种类型的数据。 下述图&#xff1a;是生成数字数组和字符串数组。 为什么有了变量还需要定义数组呢&#xff1f;为了解决在某些场景下&#xff0c;变…