当前位置: 首页 > article >正文

【C++初阶】模板初阶

前言

在我们之前的学习中我们要实现一个交换函数,会这么写

//void Swap(int* x,int* y)
void Swap(int& x,int& y)
{
    int tmp = x;
    x = y;
    y = tmp;
}

这个函数可以实现int类型的变量进行交换,但要实现其他类型,如:double、float……等,便要使用函数重载,每当出现新的类型时就需要写一个新的对应函数,太麻烦了!

哪有什么方法可以只用一个函数就可以实现都种不同类型变量进行交换呢?

泛型编程就可以解决这种问题!!! 

泛型编程

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

它就是给编译器一个模具,不同的类型变量就相当于是不同的材料,以此来获得不同的铸件

它的本质就是把分辨类型的工作交给编译器 

模板

模板分为:函数模板和类模板

函数模板

概念:

函数模板是一个函数家族,与变量类型无关,在使用时根据实参类型生成特定类型版本

格式:

template<typename T1, typename T2,……>

返回类型 函数名(参数列表)

{}

注:typename也可以用class代替

template<typename T>
void Swap(T& a, T& b)
{
	T temp = a;
	a = b;
	b = temp;
}

int main()
{
	int x = 1, y = 2;
	Swap(x, y);
	cout << x << " " << y << endl;
	double m = 1.01, n = 2.02;
	Swap(m, n);
	cout << m << " " << n << endl;
    return 0;
}

原理:

函数模板的工作实质是将原本需要我们重复去做的事交给编译器去做,编译器根据传入实参类型来生成对应类型的函数

实例化:

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

1、隐式实例化:
template<typename T>
void Swap(T& a, T& b)
{
	T temp = a;
	a = b;
	b = temp;
}

int main()
{
	int x = 1, y = 2;
	Swap(x, y);
	cout << x << " " << y << endl;
	double m = 1.01, n = 2.02;
	Swap(m, n);
	cout << m << " " << n << endl;

    return 0;
}
2、显式实例化:

当进行不同类型变量间的类型转换时,隐式实例化就无法实现了,因为在模板中编译器一般不会自动进行类型转换,这时就可以使用显式实例化和强制类型转换

template<typename T>
T Add(const T& a, const T& b)
{
	return a + b;
}

int main()
{
	int x = 1, y = 2;
	double m = 1.01, n = 2.02;
	//强制转换
	cout << Add(x, (int)m) << endl;
	cout << Add((double)x, m) << endl;

	//显式实例化
	cout <<Add<int>(x, n) << endl;
	cout <<Add<double>(x, n) << endl;

    return 0;
}

匹配规则

1、在有非模板函数和同名模板函数时,编译器会优先使用非模板函数

2、对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而

不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数,那么将选择模板

3、模板函数不允许自动类型转换,但普通函数可以进行自动类型转换

类模板

格式:

template<class T1, class T2, ..., class Tn>

class 类模板名

{

// 类内成员定义

};

template<class T>
class Stack
{
public:
	Stack(size_t capacity = 4)
	{
		_a = new T[capacity];
		_capacity = capacity;
		_top = 0;

	}
	void push(const T& x)
	{
		if (_top >= _capacity)
		{
			/*_a = (T*)malloc(sizeof(T) * n);
			if (nullptr == _a)
			{
				perror("malloc申请空间失败");
				return;
			}*/
			int newcapacity = _capacity * 2;
			T* tmp = new T[newcapacity];
			delete[] _a;
			memcpy(tmp, _a, sizeof(T) * _top);
			_capacity = newcapacity;
		}
		_a[_top++] = x;
	}
private:
	T* _a;
	size_t _capacity;
	size_t _top;
};

实例化:

类模板实例化和函数模板实例化不一样,它需要在类模板名后面加<>,然后将实例化类型放在<>中,类模板名字不是真正的类,而实例化的结果才是真正的类

Stack<int> s1;


http://www.kler.cn/a/588384.html

相关文章:

  • C++内存管理(复习)
  • 游戏成瘾与学习动力激发策略研究——了解“情感解离”“创伤理论”
  • OpenHarmony项目的应用在DevEco Studio配置项目中固定的一键签名
  • android ConstraintLayout布局 实战:打造复杂界面的最佳实践
  • 网络规划设计师软考个人学习资料分享
  • stl之string的详解
  • thefuck是如何帮助你提高命令行效率
  • C#开发笔记:INI文件操作
  • 分别用树型和UML结构展示java集合框架常见接口和类
  • 从Instagram到画廊:社交平台如何改变艺术家的展示方式
  • 掌握Windows命令提示符中的万能符:*号的全方位使用指南
  • Java基础编程练习第32题-定义接口(Biology、Animal)、类(Person)、子类(Pupil)(PTA选题)
  • 使用c#进行串口通信
  • 商品详情页
  • 第7章 站在对象模型的尖端3: RTTI
  • 考研系列-408真题计算机网络篇(10-17)
  • Centos 7 升级 GCC
  • 找第一个只出现一次的字符(信息学奥塞一本通-1130)
  • 基于大模型的智能客服搭建
  • doris:安全概览