IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++初阶:初识模板和泛型编程 -> 正文阅读

[C++知识库]C++初阶:初识模板和泛型编程

初识模板

1. 模板初阶

1.1 泛型编程

void Swap(int& left, int& right) { // 交换两个整型变量
	int tmp = left;
	left = right;
	right = tmp;
}
void Swap(double& left, double& right) { // 交换两个浮点型变量
	double tmp = left;
	//...
}
void Swap(char*& left, char*& right) { // 交换两个指针变量
	char* tmp = left;
	//...
}

如上述代码所示,代码模块的功能非常相似,只是处理的数据类型不同,为每种类型,都写出对应的代码,这样代码复用率太低,且可维护性低。

可以在函数中传入通用的数据类型,从而合并代码,泛型的出现就是专门解决这个问题的。泛型编程的定义就是:编写与类型无关的代码,是一种代码复用的手段

屏蔽掉数据和操作数据的细节,让算法更为通用,让编程者更多地关注算法的结构,而不是在算法中处理不同的数据类型。编程语言本质上帮助程序员屏蔽底层机器代码的实现,而让我们可以更为关注业务逻辑代码。

泛型编程在 C++ 中,就体现在模板上。可以用模板技术来抽象类型,这样可以写出类型无关的代码。模板是泛型编程的基础,模板是创建泛型类或函数的蓝图或公式。模板分为函数模板和类模板

1.2 函数模板

函数模板的定义格式

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

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

如上两种方式都可以,typename 和 class 都是用来定义模板关键字的。

为解决最开始的例子,交换两个变量的函数代码复用问题,可以使用如下的方式:

template <class T>
void Swap(T& left, T& right) {
	T tmp = left;
	left = right;
	right = tmp;
}
函数模板的原理

但当不同数据类型调用该函数模板时,使用的是同一个函数吗?

函数模板本是个蓝图,是编译器产生特定具体类型函数的模具,它本身算是模板而不是函数。模板将重复性的操作交给编译器去执行,产生了多个适用于不同类型的函数。

参数类型不同,函数栈帧必然不同,那必然不会是同一个函数。vs2019 甚至多了这样的窗口:

函数地址不同,可见调用的不是同一个函数。在代码编译阶段,对于模板函数,编译器根据传入的实参类型也推演生成对应类型的函数以供调用。

函数模板的实例化

不同类型的参数使用该函数模板的过程,称为函数模板的实例化。模板参数实例化分为两种:隐式实例化和显式实例化。

  • 隐式实例化:编译器根据实参自动推演参数的实际类型的模板实例化过程。

  • 显式实例化:函数名后<>指定模板参数的类型的实例化过程。

template <class T>
T Add(const T& rx, const T& ry) {
	return rx + ry;
}
int main()
{
	int a = 10, b = 20;
	double c = 3.33, d = 4.44;
    //1. 隐式实例化
	Add(a, b);
	Add(c, d);
    //2. 显式实例化
	Add<int>(a, d);
	Add<double>(a, d);	
    
    Add(a, d); // Err:类型不一致
	Add((double)a, d); // 提前强转参数类型
    return 0;
}

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

函数模板的匹配原则
int Add(const int& rx, const int& ry) // 适用于int类型
{
	return rx + ry;
}
template <class T> 
T Add(const T& rx, const T& ry) // 通用类型模板
{
	return rx + ry;
}
  • 当存在和函数模板同名同参数列表的函数时,编译器会优先调用普通函数而非模板

存在普通函数说明开发者更想使用函数而非模板,调用函数也可以省去模板实例化的环节。

  • 函数模板不允许自动类型转换,但普通函数传参时允许发生隐式类型转换。

1.3 类模板

使用typedef类型重命名不能够支持所有类型,且不能用同一个类创建不同类型成员的对象。只是将一个固定的类型重命名,并不属于泛型编程。

类模板的定义格式

定义格式和函数模板类似:

template <class T1, class T2,..., class Tn>
class 类模板名 {
	//...  
};
template <class T>
class Stack {
public:
	Stack(int capacity = 4) 
		:_top(0), _capacity(capacity)
	{
		_data = new T[capacity];
	}
	~Stack() {
		delete[] _data;
		_data = nullptr;
		_top = _capacity = 0;
	}
    void Push(T x) {
		//....	
	}
private:
	T* _data;
	int _top;
	int _capacity;
};
类模板的实例化

类模板和函数模板的实例化有所不同,类模板实例化必须要在模板名后跟<>并指明类型。类模板是模板而不是类,实例化后生成的类才是真正的类。

//Stack是类模板名,Stack<int>才是类型
Stack<int> st1;
Stack<double> st2;

成员函数声明定义分离,函数体定义在类外时,不仅要声明函数所属类域,还要声明模板类型。

template <class T> // 声明模板类型
void Stack<T>::Push(T x) { // 声明所属类域
	_data[top++] = x;
	//...
}

?

2. STL 简介

STL(standard template libaray)是 C++ 标准库的重要组成部分:标准模板库。STL 不仅是一个可复用的组件库,而且
是一个包罗数据结构与算法的软件框架。

原始版本
Alexander Stepanov、Meng Lee 在惠普实验室完成的原始版本,本着开源精神,他们声明允许任何人任意运用、拷贝、修改、传播、商业使用这些代码,无需付费。唯一的条件就是也需要向原始版本一样做开源使用。也成为 HP 版本,是所有STL实现版本的始祖。
P. J. 版本
由 P. J. Plauger 开发,继承自 HP 版本,被 Windows Visual C++ 采用,不能公开或修改,缺陷:可读性比较低,符号命名比较怪异。
RW版本
由 Rouge Wage 公司开发,继承自 HP 版本,被 C++ Builder 采用,不能公开或修改,可读性一般。
SGI版本
由 Silicon Graphics Computer Systems,Inc 公司开发,继承自 HP 版 本。被 GCC(Linux) 采用,可移植性好,可公开、修改甚至贩卖,从命名风格和编程风格上看,阅读性非常高。学习 STL 要阅读部分源代码,主要参考的就是这个版本。

网上有句话说:“不懂 STL,不要说你会 C++ ”。STL 是 C++ 中的优秀作品,有了它的陪伴,许多底层的数据结构以及算法都不需要自己重新造轮子,站在前人的肩膀上,健步如飞的快速开发。

STL 的缺陷

  1. STL库的更新太慢了。这个得严重吐槽,上一版靠谱是C++98,中间的C++03基本一些修订。C++11出来已经相隔了13年,STL才进一步更新。
  2. STL现在都没有支持线程安全。并发环境下需要我们自己加锁。且锁的粒度是比较大的。
  3. STL极度的追求效率,导致内部比较复杂。比如类型萃取,迭代器萃取。
  4. STL的使用会有代码膨胀的问题,比如使用vector/vector/vector这样会生成多份代码,当然这是模板语法本身导致的。
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-02-28 15:10:05  更:2022-02-28 15:13:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 7:20:06-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码