🧸🧸🧸各位大佬大家好,我是猪皮兄弟🧸🧸🧸
模板可以有函数模板和类模板
文章目录
一、模板简介
模板是一个非常强大的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++类和对象剩下重要知识点进行了总结,感谢大家的支持,类和对象的内容就更新完了,后面我会继续更新内存管理有关方面的内容!