【C++】模板初阶,了解函数模板和类模板的使用&&一些可能出现的问题

🧸🧸🧸各位大佬大家好,我是猪皮兄弟🧸🧸🧸
在这里插入图片描述模板可以有函数模板和类模板

一、模板简介

模板是一个非常强大的C++功能,STL的各种组件也是基于模板的。所以,有必要了解一下C++的模板。

有了模板,就可以针对广泛的类型去写代码
泛型编程:编写与类型无关的通用代码,是代码复用的一种手段,模板时泛型编程的基础

模板的参数又叫做虚拟类型参数
<>里面的参数又叫做模板实参表

二、模板的声明和定义

1.模板的声明

template<typename T>  int compare (T t1, T t2);
template<typename T>  class compare;
//也可以用typelate<class T>,现阶段五区别

2.函数模板的定义


template <typename T>
int compare(T & t1, T & t2)
{
    return t1>t2;
}

3.定义一个类模板

template <typename T>
class compare
{
public:
    
private:
    T _value;
};

三、模板工作原理

模板定义并不是真正定义了一个函数或者类,而是编译器通过程序员写出的模板和形参自动生成对应版本的定义,这个过程就叫做模板的推演和实例化,编译器生成的版本通常被称作模板的实例,编译器生成的具体过程,类似于宏替换
由于编译器不回去调用模板本身,所以一般模板是放在头文件中的

四、函数模板

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

函数模板格式:

//处理用typename以外,还可以用class T1,classT2....
template<typename T1,typename T2.....>
//下面写一个函数

现阶段用typename和class都是一样,T是随便起的名字,一般用的大写首字母

template<typename T>
//template<class T>
void Swap(T&left,T&right)
{
	T tmp = left;
	left=right;
	right=tmp;
}
/*注意,泛型的Swap不能用异或来实现,因为异或
只针对整型,对于浮点数就不行了,对自定义类型更扯
*/
int main()
{
	int a=1,b=2;
	double x=1.1,y=2.2;
	//1.写模板
	Swap(a,b);
	Swap(x,y);
	//2.函数重载
}

对于不同的类型,会进行推演和实例化,因为需要生成特定的函数,不是使用的模板,所以需要实例化
在这里插入图片描述
因为有了模板,所以编译的时间也会相对长

不同的函数对应的地址也是不同的,上面的三个函数调用的是三个地址,也就说明了不是去调用的模板,而是另外生成了三个。

五、函数模板的实例化

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

1.隐式实例化

让编译器根据实参推演模板参数的实际类型
模板的参数是不能隐式类型转换的,普通函数可以

template<typename T>
T Add(const T&left,const T&right)
{
	return left+right;
}
int main()
{
	Add(1.1,2);//报错
	return 0;
}

报错原因:
在传参的时候是可以隐式类型转换的,但是在推演实例化的时候就过不去了
解决方法:
a.在传参的时候强制类型转换去解决
b.显示实例化(下面)
c.多模板参数

2.显示实例化

指定实例化的类型

template<typename T>
void Swap(T&left,T&right)
{
	T tmp=left;
	left=right;
	right=tmp;
}
int main()
{
	int a=10,b=20;
	Swap<int>(a,b);
	return 0;
}

像刚才说的哪种,必须要显示实例化才行,如下

template<typename T>
T Add(const T&left,const T&right)
{
	return left+right;
}
int main()
{
	int a=10,b=20;
	double x=1.1,y=2.2;
	int sum = Add<int>(a+x);
	double res = Add<double>(a+x);
	return 0;
}

想要在模板推演实例化的时候进行类型转换,就需要显示实例化去执行实例化的类型。不然的话推演实例化过程中是不会发生隐式类型转换的,编译器报错。

3.其它问题

首先是可以存在多个模板参数的

template<typename T1,typename T2>
T1 Add(const T1& left,const T2& right)
{
	return left+right;
}

函数模板和普通的函数可以同时存在,有现成的就直接用

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

int Add(int left,int right)//这个本来就是拷贝,不需要const
{
	return left+right;
}

六、类模板

1.类模板与模板类

类模板是一个模板,是类的抽象
模板类是一个类,用类模板生成的类

2.类模板的实例化

类模板都是显示实例化

template<class T>
//template<typename T>
class Stack
{	
public:
	Stack(size_t capacity=4)
		:_a(nullptr)
		,top(0)
		,capacity(0)
	{
		_a= new T[capacity];
		_capacity = capacity;
		_top=0;
	}
private:
	T* _a;
	int _top;
	int _capacity;
};
int main()
{
	Stack<int> st1;
	Stack<char> st2;
	Stack<double> st3(100);
	return 0;
}

另外,模板是不支持分离编译的,有支持的方法,但非常麻烦,后面再说,也就是说模板并不能够声明放在.h,定义放在.cpp,原因后面再说,只支持放在一个文件里。其次,模板也是可以给缺省值的,不过这个缺省值是类型,template<typename T = int>,不过就算是有了缺省值,实例化 的时候<>还是要加上。

七、总结

上面对C++类和对象剩下重要知识点进行了总结,感谢大家的支持,类和对象的内容就更新完了,后面我会继续更新内存管理有关方面的内容!
在这里插入图片描述

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猪皮兄弟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值