文章目录
- 前言
- 函数模版
- 函数模版的原理
- 函数模版的实例化
- 类模版
- 类模版的实例化
前言
当我们使用一个通用的函数:
//为每一个类型都编写一个重载版本
void Swap(int& left, int& right)
{int temp = left;left = right;right = temp;
}
void Swap(double& left, double& right)
{double temp = left;left = right;right = temp;
}
void Swap(char& left, char& right)
{char temp = left;left = right;right = temp;
}
这种方法的缺点是显而易见的:随着需要交换的类型的增加,你需要不断地编写新的重载函数。这不仅繁琐,而且不灵活,因为它不能自动适应未来可能出现的新类型。
函数模板提供了一种更加灵活和通用的解决方案。你可以定义一个模板函数,该函数可以接受任意类型的参数,并在编译时根据传入的参数类型生成相应的函数版本。
函数模版
函数模版的格式:
template<typename T1, typename T2,…,typename Tn>
返回值类型 函数名(参数列表){}
//函数模版
template<class T>
void Swap(T& m, T& n)
{T tmp = m;m = n;n = tmp;
}
注意:typename是用来定义模板参数关键字,也可以使用class(切记:不能使用struct代替class)
template<typename T>
void Swap(T& m, T& n)
{T temp = m;m = n;n = temp;
}
template<class T>
void Swap(T& m, T& n)
{T tmp = m;m = n;n = tmp;
}
int main()
{int i = 1, j = 2;double x = 1.1, y = 2.2;Swap(i, j);Swap(x, y);//Swap(i, x); 函数模版不能传不同类型的参数return 0;
}
函数模版的原理
函数模版本身并不是函数,模版只是将我们做的事重复的事交给了编译器
函数模版的实例化
用不同类型的参数使用函数模板时,称为函数模板的实例化。模板参数实例化分为:隐式实例化和显式实例化。
这里就是要解决这个问题
有两种处理方式
- 强制类型转换
- 使用显式实例化
template<class T>
void Swap(const T& m, const T& n)
{T tmp = m;m = n;n = tmp;
}
int main()
{int i = 1, j = 2;double x = 1.1, y = 2.2;//推导实例化(自己动手强转)Swap(i, (int)x);Swap((double)i, x);//显示实例化Swap<int>(i, x);return 0;
}
如果我就要用 Swap(i,x) 来实现呢?
template<class T1,class T2>
T1 Swap(const T1& m, const T2& n)
{T1 tmp = m;m = n;n = tmp;
}
有种场景我们必须用显示实例化:
template<class T>
T* func1(int n)
{return new T[n];
}
int main()
{//func1(10); 编译器无法推导出类型int* p = func1<int>(10);return 0;
}
如果函数和模板同时存在,会先调用函数
template<class T>
T ADD(const T& left, const T& right)
{return left + right;
}
int ADD(const int& x, const int& y)
{return (x + y) * 10;
}
int main()
{int a = 5;int b = 10;cout<<ADD(a, b)<<endl;return 0;
}
类模版
类模版的格式:
template<class T1, class T2, ..., class Tn>
class 类模板名
{// 类内成员定义
};
类模版实现栈
template<class T>
class Stack
{
public:Stack(int n = 4):_arr(new T[n]),_size(0),_capacity(n){}~Stack(){delete[] _arr;_arr = nullptr;_size = _capacity = 0;}void Push(const T& x){if (_size == _capacity){T* tmp = new T[_capacity * 2];memcpy(tmp, _arr, sizeof(T) * _size);delete[] _arr;_arr = tmp;_capacity *= 2;}_arr[_size++] = x;}//...
private:T* _arr;int _size;int _capacity;
};
将栈的所有数据和方法封装在类内部,所以只有类成员函数才可以访问(最好不要类里声明,类外定义,除非在类外使用template<>语法来指明你正在定义的是哪个模板参数的成员函数),而且,通过类模版,不同的类型都可以实现栈,安全性也得到了提升。
template<class T>
void Stack<T>::Push(const T& x)
{if (_size == _capacity){T* tmp = new T[_capacity * 2];memcpy(tmp, _arr, sizeof(T) * _size);delete[] _arr;_arr = tmp;_capacity *= 2;}_arr[_size++] = x;
}
类模版的实例化
类模版只能使用显示实例化
int main()
{Stack<int>str1;str1.Push(1);str1.Push(2);str1.Push(3);Stack<double>str2;str2.Push(1.1);str2.Push(2.2);str2.Push(3.3);return 0;
}
希望这篇博客对你有所帮助!!!