模板(Template)
- 模板就是C++实现代码重用机制的一种工具
- 它可以实现类型参数化,即把类型定义为参数, 从而实现了真正的代码可重用性。
- 可以使用模板来定义函数和类
当你定义一个如下函数,想要计算一个数的平方
int square(int x){
return x*x;
}
可你想要函数也能对double类型的数进行平方,于是接着写
double square(double x){
return x*x;
}
基于C++的函数重载,你如愿完成了这个功能
int main(){
cout<<square(5)<<endl;
cout<<square(5.5)<<endl;
return 0;
}
是不是觉得写了两个功能一模一样的函数,只是改变了形参类型,有点蠢?那让我们来看Template是怎么做的
template <typename T>//函数模板
T square(T x){
return x*x;
}
int main(){
cout<<square<int>(5)<<endl;
cout<<square<double>(5.5)<<endl;
return 0;
}
是不是很神奇?函数模板在这里仅仅是声明了一个求平方函数的描写叙述,还不是一个能够直接运行的函数。只有用实參的数据类型取代类型參数标识符T之后(实例化),才会产生真正的函数。同时函数模板在调用时能够自动鉴别实参的数据类型(隐式实例化),因此上方主函数里的cout<<square<int>(5)<<endl;
还可以改写成cout<<square(5)<<endl;
,使代码更加简练。
下面再通过一个例子介绍类模板
template <typename T>//类模板,也可定义为template<class T>
class iVector{
T arr[1000];
int size;
public:
BoVector():size(0){}
void push(T x){
arr[size]=x;size++;
}
void print() const {
for(int i=0;i<size;i++){
cout<<arr[i]<<endl;
}
}
};
与函数模板类似,类模板不是一个类,而是一个模板,只有实例化后才会成为一个类,因此类模板需要这样来使用
int main(){
//类模板必须要指明数据格式(实例化),即 iVector<int> iv,这一点与函数模板不同
iVector<int> iv;
iv.push(2);
iv.push(5);
iv.push(8);
iv.push(9);
iv.print();
return 0;
}
最后我们将函数模板和类模板结合起来使用,感受模板带来的便捷与效率
#include<iostream>
using namespace std;
template <typename T>//函数模板
T square(T x){
return x*x;
}
template <typename T>//类模板
class iVector{
T arr[1000];
int size;
public:
iVector():size(0){
}
void push(T x){
arr[size]=x;size++;
}
T get(int i) const {
return arr[i];
}
int getsize()const{
return size;
}
void print() const {
for(int i=0;i<size;i++){
cout<<arr[i]<<endl;
}
}
};
template<typename T>
iVector<T> operator*(const iVector<T>& rhs1,iVector<T>& rhs2){//类模板的运算符重载
iVector<T> res;
for(int i=0;i<rhs1.getsize();++i){
res.push(rhs1.get(i)*rhs2.get(i));
}
return res;
}
int main(){
iVector<int> iv;
iv.push(2);
iv.push(5);
iv.push(8);
iv.push(9);
cout<<"Print squared iv:"<<endl;
iv=square(iv);
iv.print();
return 0;
}
标准模板类STL(C++ Standard Template Library)介绍
STL(Standard Template Library,标准模板类)是C++语言内置的一个基础模板集合,包含了各种常用的存储数据的模板类及相应的操作函数,你可以将STL理解为STL= Containers(存储数据的容器)+Algorithms(处理数据的算法)+Iterators(数据和算法的桥梁)
- 容器(container):用来管理某类对象的集合,容器可以是array、vector、tree、hash map、set等;
- 迭代器(iterator):用来在一个对象集合内遍历元素,这个对象集合或许是个容器,或许是容器的一部分。迭代器和寻常的指针类似,调用operator ++ 就累进,调用operator * 就访问被指向的元素值,你可以把迭代器视作一种智能指针,能够把”前进至下一元素“的意图转换为合适的操作;
- 算法(algorithm):用来处理集合内的元素,它们可以出于不同的目的而插入、删除、修改、查找、排序、使用元素,通过迭代器的协助,我们只需撰写一次算法,就可以将它应用于任意容器,因为所有容器的迭代器都提供一致的接口。
下面是一个调用STL的小栗子
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
//container为vector
vector<int> vec;
//algorithm为push_back(从尾部添加元素)
vec.push_back(4);
vec.push_back(1);
vec.push_back(8);
//iterator为itr1,itr2,i
vector<int>::iterator itr1=vec.begin();//[begin,end)
vector<int>::iterator itr2=vec.end();
for(vector<int>::iterator i=itr1;i!=itr2;++i){
cout<<*i<<" ";
}
cout<<endl;
//algorithm为sort(排序)
sort(itr1,itr2);
for(vector<int>::iterator i=itr1;i!=itr2;++i){
cout<<*i<<" ";
}
return 0;
}
使用STL的理由
- 代码重用,不需要重复造轮子
- 效率高(又快又节省资源)
- 准确,避免写出更多的 bug
- 代码简洁,可读性高
- 即标准化又保证可用性
有关STL的详细用法及介绍我会在后面的文章中持续更新,欢迎关注!