C++ || 模板初阶 | 函数模板 | 类模板

泛型编程

泛型编程,编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。

  • 可以理解为活字印刷术类似的方式。

函数模板

函数模板概念

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

解决函数作用相同,但是参数类型不同,得写好几个参数不同但函数功能相同的代码,函数模板就是解决这个问题。

本来应该我们做的重复的事情交给了编译器。

函数模板语法

template<typename T1,typename T2,...,typename Tn>
返回类型 函数名(参数列表){}
  • typename是定义模板参数关键字
  • 可以使用class,但不能是struct

函数模板使用案例

#include <stdio.h>
#include <iostream>
using namespace std;
//template<typename T>
template<class T>
//typename是定义模板参数的关键字,
//也可以使用class,但不能是struct
void Swap(T& left, T& right)
{
	T temp = left;
	left = right;
	right = temp;
}
int main()
{
	int a = 3, b = 5;
	Swap(a, b);
	cout << "a=" << a << " " << "b=" << b << endl;//a=5 b=3
	double d = 2.63, e = 9.35;
	Swap(d, e);
	cout << "d=" << d << " " << "e=" << e << endl;//d=9.35 e=2.63
	return 0;
}

函数模板原理

  • 函数模板,本身并不是函数;
  • 编译器产生特定具体类型函数的模具;
  • 在编译器编译阶段,编译器根据传入的实参类型推演生成对应类型的函数
  • 例如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码。

函数模板实例化

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

隐式实例化

隐式实例化,让编译器自己根据实参推演模板参数的实际类型。

template <typename T>
T Add(const T& left, const T& right)
{
	return left + right;
}
int main()
{
	int a1 = 10, a2 = 20;
	double d1 = 10.9, d2 = 45.8;
           //隐式实例化
	cout << Add(a1, a2) << endl; //30
	cout << Add(d1, d2) << endl;//56.7

	// Add(a1, d1) 会报错 
	// 编译器无法确定此处到底该是将T确定为int还是double
	// 两种处理方式:①用户强转 Add(a1, (int)d1) ;②显示实例化 Add<int>(a1, d1) 
	//cout << Add(a1, d1) << endl;//56.7
	cout << Add(a1, (int)d1) << endl;//56.7
	return 0;
}

显示实例化

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

template <typename T>
T Add(const T& left, const T& right)
{
	return left + right;
}
int main()
{
	int a = 10;
	double d = 10.9;
	        //显示实例化
	cout << Add<int>(a, d) << endl;//20
	return 0;
}

模板参数的匹配规则

  • 一个非模板函数可以和一个同名模板函数同时存在。

非模板函数与同名模板函数同时存在时:

  • 调用函数与非模板函数匹配时,编译器不需要推演特化;
  • 有显示实例化,编译器进行函数模板推演;
  • 优先调用非模板函数;
  • 模板函数不允许自动类型转换,但普通函数可以进行自动类型转化。

类模板

将类中的成员变量或者成员函数的参数数据类型进行模板化。

类模板名字不是真正的类,实例化的结果才是真正的类。

类模板语法

  • 类模板中函数放在类外进行定义时,需要加模板参数列表。
template<class T1,class T2,...,class Tn>
class 类模板名
{
	//类成员
};

//类模板函数在类外定义,加模板参数列表
template<class T1,class T2,...,class Tn>
类模板名<T1/T2/.../Tn>::类模板成员函数名()
{
    函数功能
}

int main()
{
    类模板名<实例化类型> 类对象实例化名字;//Date d;
}

类模板实例化

类模板名<实例化的类型> 实例化类对象名;
//Date d1;

类模板名字不是真正的类,实例化的结果才是真正的类。

类模板使用案例

template<class T>
class Vector
{
private:
	T* _pData;
	size_t _size;
	size_t _capacity;

public:
	Vector(size_t capacity = 10)
		:_pData(new T[capacity])
		,_size(0)
		,_capacity(capacity)
	{

	}

	~Vector();
};

template <class T>
Vector<T>::~Vector()
{
	if (_pData)
		delete[] _pData;
	_size = 0;
	_capacity = 0;
}

int main()
{
	Vector<int> S1;
	//Vector类名 int参数类型
}

相关推荐

  1. C++:vector模拟实现(含模板

    2024-02-08 07:06:02       16 阅读
  2. C++】模板

    2024-02-08 07:06:02       39 阅读

最近更新

  1. Android IdleHandler源码分析

    2024-02-08 07:06:02       0 阅读
  2. docker-1

    docker-1

    2024-02-08 07:06:02      0 阅读
  3. Git批量删除本地h和远程分支说明

    2024-02-08 07:06:02       0 阅读
  4. mvccaa

    2024-02-08 07:06:02       1 阅读
  5. Linux 常用指令详解

    2024-02-08 07:06:02       1 阅读
  6. 第2章 源码编译构建LAMP

    2024-02-08 07:06:02       1 阅读
  7. 数据库doris中的tablet底层解析

    2024-02-08 07:06:02       1 阅读
  8. 使用Python threading模块创建多线程程序

    2024-02-08 07:06:02       1 阅读
  9. 探索数据的奥秘:sklearn中的聚类分析技术

    2024-02-08 07:06:02       1 阅读

热门阅读

  1. [缓存] - Redis

    2024-02-08 07:06:02       32 阅读
  2. SpringCache缓存快速实现注解

    2024-02-08 07:06:02       31 阅读
  3. Vscode SSH使用云服务器访问内网主机

    2024-02-08 07:06:02       35 阅读
  4. reactive 与 ref 的区别

    2024-02-08 07:06:02       36 阅读
  5. 项目中常用的一些数据库及缓存

    2024-02-08 07:06:02       34 阅读
  6. 设计模式(前端)

    2024-02-08 07:06:02       31 阅读