C++ 泛型编程,函数模版和类模版
1.泛型编程
泛型编程:编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础
就比如说活字印刷术,就是提供一个模具,然后根据模具来印刷出不同的字。
泛型编程跟着类似,提供一个模版,根据这个模版由编译器自动生成不同的函数或者类
2.函数模版
2.1为什么要有函数模版
在c语言中,我们想交换两个整数、交换两个浮点数、交换自定义类型类型,我们必须自己手动写n个函数!!!并且每个函数的函数名都不一样!!!
void SwapInt(int& a,int& b)
{
int c = a;
a = b;
b = c;
}
void SwapDouble(double& a, double& b)
{
double c = a;
a = b;
b = c;
}
int main()
{
int a1 = 1, b1 = 2;
SwapInt(a1, b1);
cout << a1 << " " << b1 << endl;
double a2 = 1.1, b2 = 2.2;
SwapDouble(a2, b2);
cout << a2 << " " << b2 << endl;
return 0;
}
有没有一种方法能使我们不用再写很多个函数,只用写一个函数(模版),就能完成各个类型的交换呢?这时候函数模版就登场了
2.2怎么使用函数模版
模版格式:
template<class T1,class T2,class T3...>
返回值 函数名(函数参数){ 函数体 }
template<class T>
void Swap(T &a ,T &b)
{
T c = a;
a = b;
b = c;
}
int main()
{
int a1 = 1, b1 = 2;
Swap(a1, b1);
cout << a1 << " " << b1 << endl;
double a2 = 1.1, b2 = 2.2;
Swap(a2, b2);
cout << a2 << " " << b2 << endl;
return 0;
}
2.3函数模版的实例化
这里我们提供的swap是仅仅只是一个函数模版而已,并不是真正的函数,用不同类型的参数使用函数模板时,需要由编译器自动生成一个相应的函数,这就叫做函数模版的实例化!!!
模版的实例化分为显示实例化和隐式实例化
2.3.1隐式实例化
由编译器识别实参类型,推导出模版参数的类型
template<class T>
void Swap(T &a ,T &b)
{
T c = a;
a = b;
b = c;
}
int main()
{
int a1 = 1, b1 = 2;
Swap(a1, b1);
double a2 = 1.1, b2 = 2.2;
Swap(a2, b2);
return 0;
}
由传进来的参数推导出T的类型,这种就叫做隐式实例化
2.3.2显示实例化
在函数名后的<>中指定所传的具体类型
template<class T>
void Swap(T &a ,T &b)
{
T c = a;
a = b;
b = c;
}
int main()
{
int a1 = 1, b1 = 2;
Swap<int>(a1, b1);
double a2 = 1.1, b2 = 2.2;
Swap<double>(a2, b2);
return 0;
}
3.类模版
3.1为什么需要有类模版
当我们需要两个栈,一个栈存int类型,一个存double类型时,我们又只能自己写两个不同的类,这两个类 类名不同,但是类中除了类型,其他的都是一样的!!!
class StackInt
{
public:
StackInt(int capacity = 4)
{
_a = new int[capacity];
_top = 0;
_capacity = capacity;
}
~StackInt()
{
delete[] _a;
_a = nullptr;
_top = _capacity = 0;
}
private:
int* _a;
int _top;
int _capacity;
};
class StackDouble
{
public:
StackDouble(int capacity = 4)
{
_a = new double[capacity];
_top = 0;
_capacity = capacity;
}
~StackDouble()
{
delete[] _a;
_a = nullptr;
_top = _capacity = 0;
}
private:
double* _a;
int _top;
int _capacity;
};
int main()
{
StackInt st1;
StackDouble st2;
return 0;
}
这时候就需要用到我们的类模版来解决这个问题了.
3.2怎么使用类模版
模版格式:
template<class T1,class T2,class T3...>
class 类名 { 成员函数和成员变量 };
template<class T>
class Stack
{
public:
Stack(int capacity = 4)
{
_a = new T[capacity];
_top = 0;
_capacity = capacity;
}
~Stack()
{
delete[] _a;
_a = nullptr;
_top = _capacity = 0;
}
private:
T* _a;
int _top;
int _capacity;
};
int main()
{
Stack<int> st1;
Stack<double> st2;
return 0;
}
3.3类模版的实例化
类模版的实例化和函数模版的实例化不同,类模版的实例化是在类名后加<>,在<>中加上实例化的类型,
类模板名字不是真正的类,而实例化的结果才是真正的类
。
Stack是类名
Stack<int>是类型