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++知识库]模板

一.泛型编程

编写一种和类型无关的代码,让编译器根据实际数据类型进行推导
模板是泛型编程的基础

二.模板

模板可以分为函数模板和类模板两种类型

1.函数模板

一种根据实际类型推导类型的函数家族

1) 函数模板的格式

//typename也可以使用class替换
template<typename T1, typename T2,......,typename Tn>
返回值类型 函数名(参数列表){}

示例:

template<class T>
T ADD(T a, T b)
{
	return a + b;
}

2)函数模板的原理

函数模板本身并不是函数,是编译器根据实际使用方式产生特定具体类型函数的模具。在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。

3)函数模板的实例化

用不同类型的参数使用函数模板时,称为函数模板的实例化
根据实例化方式的不同,可以分为隐式实例化和显示实例化两种类型
隐式实例化
让编译器根据实参推演模板参数的实际类型

隐式实例化示例:

int a = 1, b = 2;
int ans = ADD(a, b);

隐式实例化存在的问题:
对于类型不匹配时,编译器会报错,可以进行强制类型转换

	int a = 1000;
	double b = 24.0;
	/*
	//error
	int ans = ADD(a, b);
	*/
	int ans = ADD(a, static_cast<int>(b));

错误:
在这里插入图片描述

显示实例化
在函数名后的<>中指定模板参数的实际类型

4)模板参数的匹配规则

  • 一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数
  • 对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板
  • 模板函数不允许自动类型转换,但普通函数可以进行自动类型转换

2.类模板

一个类中的某些数据并不是固定的,而是根据实际的需要使用特定的数据类型,这样的模板就是一个类模板

1)类模板的格式

template<class T1, class T2, ..., class Tn>
class 类模板名
{
 // 类内成员定义
};

示例:

template<class T>
class Stack
{
private:
	T* _data;
	int _capacity;
	int curSz;
};

2) 类模板的实例化

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

示例:

Stack<int> st_Int;
Stack<TreeNode*> st_Tree;

三.模板参数

模板参数分为类型形参与非类型形参

1) 类型形参

出现在模板参数列表中,跟在class或者typename之后的参数类型名称

2) 非类型形参

用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用

示例:

//类型模板参数
template<class T>
class Vector
{
public:
	//非类型模板参数
	Vector(int sz)
	{}
private:
	T* _data;
	int _size;
	int _capacity;
};

3) 使用注意事项

浮点数、类对象以及字符串是不允许作为非类型模板参数的;

非类型的模板参数必须在编译期就能确认结果;

四.模板特化

有些场景下,需要对于特殊类型进行特殊化实现,这就是模板特化
模板特化分为函数模板特化和类模板特化

1. 函数模板特化

1)特化的步骤

  1. 必须要先有一个基础的函数模板,特化是在模板已经存在的前提下进行的;
  2. 关键字template后面接一对空的尖括号<>
  3. 函数名后跟一对尖括号,尖括号中指定需要特化的类型
  4. 函数形参表: 必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报一些奇怪的错误

示例:

struct Date
{
	Date(int year = 2021, int month = 10, int day = 11)
		:_year(year)
		, _month(month)
		, _day(day)
	{}

	int _year;
	int _month;
	int _day;
};

//函数模板是特化的前提
template<class T>
bool IsEqual(const T& a, const T& b)
{
	return a == b;
}

//针对特殊类型的特化处理
template<>
bool IsEqual<Date>(const Date& d1, const Date& d2)
{
	return d1._year == d2._year && d1._month == d2._month && d1._day == d2._day;
}

void test()
{
	bool ret = IsEqual(1, 2);
	Date d1(2021, 1, 2);
	Date d2;
	ret = IsEqual(d1, d1);
}

2. 类模板特化

根据使用对象的不同分为全特化和偏特化两种类型
特化的前提是已经有一个模板

1) 全特化

模板参数列表中所有的参数都确定化

示例:

template<class T1, class T2>
class Data
{
public:
	Data() { cout << "Data<T1, T2>" << endl; }
private:
	T1 _d1;
	T2 _d2;
};

template<>
class Data<int, char> {
public:
	Data() { cout << "Data<int, char>" << endl; }
private:
	int _d1;
	char _d2;
};

void TestVector()
{
	Data<int, int> d1;
	Data<int, char> d2;
}

2) 偏特化

针对模板参数进一步进行条件限制

偏特化的两种表现方式:
部分特化
将模板参数类表中的一部分参数特化
参数更进一步的限制
针对模板参数进一步做出条件限制

根据模板进行两种偏特化示例:

//模板原型
template<class T1, class T2>
class Data
{
public:
 Data() {cout<<"Data<T1, T2>" <<endl;}
private:
 T1 _d1;
 T2 _d2;
};

//将第一个参数特化为int
template<class T2>
class Data<int, T2>
{
public:
	Data() { cout << "Data<int, T2>" << endl; }
private:
	int _d1;
	T2 _d2;
};

//对参数进一步限制
template<class T1, class T2>
class Data<T1*, T2*>
{
public:
	Data() { cout << "Data<T1*, T2*>" << endl; }
private:
	T1* _d1;
	T2* _d2;
};

五.模板的分离编译

1.分离编译

一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件链接起来形成单一的可执行文件的过程称为分离编译模式

2.模板分离编译带来的问题

C++编译器不支持模板的分离编译
如果模板的声明与定义分离开,在头文件中进行声明,源文件中完成定义,那么在编译期间程序会去源文件中找对应的实现,但是此时的模板只是一个模具,源文件中找不到实际的实现,因此编译器就会报错

解决办法:
将声明和定义放在一起

六.模板的优缺点

优点:
实现了代码复用,提高了开发效率;
增强了代码的灵活性;
缺点:
模板会导致代码膨胀问题,也会导致编译时间变长;
出现模板编译错误时,错误信息非常凌乱,不易定位错误;

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-12 23:15:23  更:2021-10-12 23:16:26 
 
开发: 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年5日历 -2024/5/19 22:24:58-

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