Lesson 04 模板入门

C++:渴望力量吗,少年?

文章目录

  • 一、泛型编程
    • 1. 引入
    • 2. 函数模板
        • (1)函数模板概念
        • (2)函数模板格式
        • (3)函数模板的原理
        • (4)函数模板的实例化
        • (5)模板参数的匹配原则
    • 3. 类模板
        • (1)类模板的定义格式
        • (2)类模板的实例化


一、泛型编程

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

使用函数重载虽然可以实现,但是有以下几个不好的地方:
(1)重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函数
(2)代码的可维护性比较低,一个出错可能所有的重载均出错
  因此,特意引入了泛型编程的概念,即编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。而模板又分为函数模板和类模板

2. 函数模板

(1)函数模板概念

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

(2)函数模板格式

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

template<class T>
void Swap(T& left, T& right)//这里要使用&,不然无法交换实参
{T temp = left;left = right;right = temp;
}
int main()
{int i = 0, j = 1;Swap(i, j);double x = 1.1, y = 2.2;Swap(x, y);return 0;
}

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

(3)函数模板的原理

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

(4)函数模板的实例化

  用不同类型的参数使用函数模板时,称为函数模板的实例化。模板参数实例化分为:隐式实例化和显式实例化。
  隐式实例化:让编译器根据实参推演模板参数的实际类型。
  显式实例化:在函数名后的<>中指定模板参数的实际类型。
  如果类型不匹配,编译器会尝试进行隐式类型转换,如果无法转换成功编译器将会报错。

template<class T>
T Add(const T& left, const T& right)
{return left + right;
}
int main()
{cout << Add(1, 2) << endl;//隐式实例化//cout << Add(1.1, 2) << endl;//类型不一致时会报错//可以使用强制类型转换把两个类型变成一致cout << Add((int)1.1, 2) << endl;cout << Add(1.1, (double)2) << endl;// 显式实例化(直接把两个都统一类型)cout << Add<int>(1.1, 2) << endl;cout << Add<double>(1.1, 2) << endl;return 0;
}
(5)模板参数的匹配原则

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

int Add(int left, int right)//像这里既有Add函数也有Add模板,调用Add函数的时候如果参数类型符合会先使用这个Add函数
{//就相当于编译器偷个懒不去替换模板的T,直接用现成的return left + right;
}
// 通用加法函数
template<class T>
T Add(T left, T right)
{return left + right;
}template<class T>
T* func(int n)
{return new T[n];
}int main()
{int x = 0, y = 1;swap(x, y);//swap其实也是C++已经写好的模板double a = 1.1, b = 2.2;swap(a, b);cout << Add(x, y) << endl;//调用非模板函数//主要就是要注意模板的实例化cout << Add<int>(x, y) << endl;int* ptr = func<int>(10);return 0;
}

3. 类模板

(1)类模板的定义格式
template < class T1, class T2, ..., class Tn>
class 类模板名
{// 类内成员定义
};
(2)类模板的实例化

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

template<class T>
class Stack
{
public:Stack(size_t capacity = 4){cout << "Stack()" << endl;_array = new T[capacity];_capacity = capacity;_size = 0;}void Push(const T& data){CheckCapacity();_array[_size] = data;_size++;}~Stack(){cout << "~Stack()" << endl;delete[] _array;_array = nullptr;_size = _capacity = 0;}
private:T* _array;int _capacity;int _size;
};
int main()
{Stack<int> st1; // intStack<double> st2; // doublest1.Push(1);st1.Push(2);st2.Push(1.2);st2.Push(1.2);return 0;
}

  比如这段代码中Stack< int > 和 Stack< double >才是类型名。

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

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

相关文章

hypermesh学习总结(一)

1、hypermesh导入导出 2、hypermesh如何使用拓扑命令,连接多个几何体为一个? 3、hypermesh模式选择 分别有显示动力学模式explicit,标准模式Standard3D(静力学及模态等)

Linux管道的工作过程

常用的匿名管道&#xff08;Anonymous Pipes&#xff09;&#xff0c;也即将多个命令串起来的竖线。管道的创建&#xff0c;需要通过下面这个系统调用。 int pipe(int fd[2]) 我们创建了一个管道 pipe&#xff0c;返回了两个文件描述符&#xff0c;这表示管道的两端&#xff…

什么是tomcat, tomcat该如何使用?(java)

tomcat是什么? tomcat翻译过来为汤姆猫, 但是他可不是猫和老鼠中的汤姆, 而是java中的tom, 虽然java中的tomcat没有猫和老鼠那么出名, 但是他仍然是java中的中流砥柱 下图为java中的tomcat, 也就是最右边这个黄色的猫: Tomcat是Apache 软件基金会&#xff08;Apache Software …

异常语法详解

异常语法详解 一&#xff1a;异常的分类&#xff1a;二&#xff1a;异常的处理1:异常的抛出:throw2&#xff1a;异常的声明:throws3&#xff1a;try-catch捕获并处理异常 三&#xff1a;finally关键字四&#xff1a;自定义异常类&#xff1a; 一&#xff1a;异常的分类&#xf…

【机器学习】特征工程:特征选择、数据降维、PCA

各位同学好&#xff0c;今天我和大家分享一下python机器学习中的特征选择和数据降维。内容有&#xff1a; &#xff08;1&#xff09;过滤选择&#xff1b;&#xff08;2&#xff09;数据降维PCA&#xff1b;&#xff08;3&#xff09;sklearn实现 那我们开始吧。 一个数据集中…

【Python】Loguru模块更简洁的日志记录库

Loguru: 更优雅的日志记录解决方案&#xff01; loguru 是一个Python 简易且强大的第三方日志记录库&#xff0c;该库旨在通过添加一系列有用的功能来解决标准记录器的注意事项&#xff0c;从而减少 Python 日志记录的痛苦。 使用自带自带的 logging 模块的话&#xff0c;则需要…

Loguru:一个超酷的Python库

在项目中&#xff0c;了解代码运行情况至关重要&#xff0c;特别是遇到Bug需要排除问题的时候&#xff0c;而这正是日志记录发挥作用的地方。对于Python开发者来说&#xff0c;Loguru是一个简单但功能强大的日志记录库&#xff0c;它使得跟踪代码的行为变得轻松而高效。 什么是…

Nodejs--Express框架使用

目录 一.概念 二.项目目录结构 三.app.js 四.项目需要的中间件 五.Mysql连接 六.日志配置 七.实体模型配置 八.统一结果封装 九.app.js的详细配置 十.自定义登录拦截器 十一.route路由配置 十二.controller处理 十二&#xff1a;静态页面&#xff1a; 十三&#xff…

【C++入门】拷贝构造运算符重载

目录 1. 拷贝构造函数 1.1 概念 1.2 特征 1.3 常用场景 2. 赋值运算符重载 2.1 运算符重载 2.2 特征 2.3 赋值运算符 前言 拷贝构造和运算符重载是面向对象编程中至关重要的部分&#xff0c;它们C编程中的一个核心领域&#xff0c;本期我详细的介绍拷贝构造和运算符重载。 1. …

Java --- JVM之垃圾回收相关算法

目录 一、垃圾标记算法 1.1、垃圾标记阶段&#xff1a;对象存活判断 1.2、引用计数算法 1.3、可达性分析算法 1.4、GC Roots 二、对象的finalization机制 2.1、生存还是死亡&#xff1f; 三、查看GC Roots 3.1、使用MAT查看 四、使用JProfiler分析OOM 五、清除阶段算…

简单聊一聊幂等和防重

大家好&#xff0c;我是G探险者。 每年的双十一&#xff0c;618&#xff0c;电商系统都会面临这超高的流量&#xff0c;如果一个订单被反复提交&#xff0c;那电商系统如何保证这个订单之后执行一次减库存&#xff0c;扣款的操作&#xff1f; 这里就引入两个概念&#xff0c;…

【Linux进程】进程等待 与 进程替换 原理与函数使用

文章目录 一、进程等待1.1 意义 / 必要性1.2 进程等待的函数&#xff08;wait / waitpid&#xff09;1.3 status参数1.4 获取子进程status1.5 进程的阻塞等待与非阻塞等待 二、进程替换2.1 引言2.2 进程替换原理2.3 替换函数 一、进程等待 1.1 意义 / 必要性 为什么要有进程等…