目录
泛型编程
函数模板
类模板
在之前的学习中,我们学习过函数重载,可以借助一样的函数名,重载不同的参数类型,以swap函数重载int,double,char3种类型为例,我们发现还是会有一点的麻烦(也会存在代码复用率低和可维护性低,容易出错等问题),在这个基础上,衍生出了模板,泛型编程
模板的定义
template
template
template // stl中喜欢用class,class与template几乎一致
对于函数重载,我们需要多写几个函数(重复的事情)借助洗衣机来洗衣服
// 函数重载
void swap(int* a, int* b){
int tmp = *a;
*a = *b;
*b = tmp;
}
void swap(double* a, double* b){
double tmp = *a;
*a = *b;
*b = tmp;
}
void swap(char* a, char* b){
char tmp = *a;
*a = *b;
*b = tmp;
}
那么如果是用泛型,编译器用模板实例化生成对应的swap函数 就是 上面重复的函数重载的内容
template
void swap(T* a, T* b){
T tmp = *a;
*a = *b;
*b = tmp
}
// 通过泛型编程 我们不需要对swap进行多次重载,直接一次到位
虽然最终公用的是一样的main函数,但是泛型编程显然更加方便简洁,也更加高级
int main() {
int i = 10;
int j = 20;
swap(i, j);
cout << i <<" " << j << endl;
double x = 1.1;
double y = 2.2;
swap(x, y);
cout << x << " " << y << endl;
}
利用模板反汇编发现形成int类型的swap和double的swap,俩个swap不一样
这里就是,在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应的函数以供调用。比如:当double抑或是int类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后专门生成处理double类型的代码!!!
template
class Stack {
public:
Stack(size_t capacity = 4) {
_array = new T[capacity];
_capacity = capacity;
_stackTop = 0;
cout << "构造 启动!" << endl;
}
~Stack() {
delete[] _array;
_array = nullptr;
_stackTop = _capacity = 0;
cout << "析构 启动!" << endl;
}
Stack(const Stack& s) {
T* _array = new T[s._capacity];
_capacity = s._capacity;
_stackTop = s._stackTop;
}
void push(const T& value) {
_array[_stackTop] = value;
_stackTop++;
}
void pop() {
_stackTop--;
}
private:
T* _array;
int _capacity;
int _stackTop;
};
int main() {
Stack st1; // 专门为int的栈
Stack st2; // 专门为double的栈
}
这样我们通过类模板就能在不同的类型来实现啦
Rart2:当我们在想如果有一个 类函数Add,当你传入得参数不是同一个类型时,又需要怎么解决呢?就比如老妈叫你去洗碗,老爸叫你去拖地,要你同时进行那你听谁的呢?编译器就像这个“你”一样苦恼,所以就需要强制执行一个(强制类型转换),抑或是叫来爷爷来决定也就是(显示实例化)
template
T Add(const T& a, const T& b){
return a + b;
}
int main(){
cout << Add(1, 2) << endl;
// 会报错 因为传入参数编译器分不清是要返回int还是double
cout << Add(1.3, 2) << endl;
// 那么就需要强制类型转换
cout << Add((int)1.3, 2) << endl;
cout << Add(1.3, (double)2) << endl;
// 显示实例化(也可以让编译器明白需要返回什么
cout << Add(1.3, 2) << endl;
cout << Add(1.3, 2) << endl;
}
Part2:当同时有普通的add函数和函数模板add,编译器在同种且符合普通add的函数和函数模板,会优先选择普通add
int Add(int& a, int& b){
return a + b;
}
template
T Add(const T& a, const T& b){
return a + b;
}
int main(){
// 编译器为了省事不会调用函数模板 而是普通add
cout << Add(x, y) <(x,y) <
Part3:类模板的定义与声明需要放在同一个部分(文件)