文章参考:
1. 引入
在编写函数和类时,有时会出现这样的情况,具体实现方式完全一致,但因此参数类型、返回值类型、数据类型等因素的不同,导致不得不写多个函数或者类(因为C++是强类型语言,无法隐式转换,且有些类型本来就无法转换),这样无疑会增加操作难度。那么,如何简单的完成这一任务呢?
define
是一个办法,例如:
#define MAX(x,y) ((x>y) ? x : y);
这样就避免了因数据类型不同而重复编写代码。
但是,define
可能导致代码在不该替换的地方进行了替换,从而造成错误,因此C++中不主张使用宏定义。
所有一个更好的办法就是使用模板。
2. 函数模板
声明格式:有两种方式:
-
template <typename 类型参数> 返回类型 函数名(模板形参表) { 函数体 }
-
template <class 类型参数> 返回类型 函数名(模板形参表) { 函数体 }
可以定义多个类型参数:
-
template <typename 类型参数1, typename 类型参数2,> 返回类型 函数名(模板形参表) { 函数体 }
EG:
-
问题:求当前数组中最大的值。
-
代码:
#include <iostream> using namespace std; template <typename T> // template <class T> 也可以 T Max(T *array, int size = 0) { T max = array[0]; for (int i = 1 ; i < size; i++) { if (array[i] > max) max = array[i]; } return max; } int main() { int array_int[] = {783, 78, 234, 34, 90, 1}; double array_double[] = {99.02, 21.9, 23.90, 12.89, 1.09, 34.9}; int imax = Max(array_int, 6); double dmax = Max(array_double, 6); cout << "整型数组的最大值是:" << imax << endl; cout << "双精度型数组的最大值是:" << dmax << endl; return 0; }
注意:
- 在
template
语句和函数语句中不允许插入别的语句。 - 在函数模板中允许使用多个类型参数。但是,应当注意template定义部分的每个类型参数前必须有关键字
typename
或class
。 - 函数模板也可以重载。
- 函数模板与同名的非模板函数可以重载。在这种情况下,调用的顺序是:
- 寻找一个完全匹配的非模板函数。
- 如果找不到,再找函数模板。
3. 类模板
建立类模板,主要是因为有时候,类的数据类型、成员函数的返回类型、形参类型不确定,因此使用类模板。语法与函数模板相似。下面是一个案例:
template <typename T>
class Three{
private:
T x, y, z;
public:
Three(T a, T b, T c) {
x = a; y = b; z = c;
}
T sum() {
return x + y + z;
}
T mul();
}
// 如果在类外定义类模板的成员函数,需要加上模板声明,且函数名前要加上"类名<类型参数>::"
template <typename T>
T Three<T>::(){
return x * y * z;
}
EG:
-
代码:
#include <iostream> #include <cstring> using namespace std; const int CAPACITY = 10; template <typename T> class Stack{ private: T stack[CAPACITY]; // 这里使用数组,简化初始化操作 int top; public: void init(); void push(T t); T pop(); }; // 必须加上<T>定义,否则无法识别类 template <typename T> void Stack<T>::init(){ top = 0; } template <typename T> void Stack<T>::push(T t){ if(this->top == CAPACITY){ cout << "stack is full"<< endl; return; } stack[top++] = t; } template <typename T> T Stack<T>::pop(){ if (top == 0){ cout << "stack is empty" << endl; return 0; } return stack[--top]; } int main(void){ // 注意:在初始化模板类时需要指定参数类型 Stack<int> s; s.init(); s.push(3); s.push(5); cout << s.pop() << endl; cout << s.pop() << endl; cout << s.pop() << endl; return 0; }
-
输出:
5 3 stack is empty 0
注意:
- 只要是模板类的类外声明,在类名后面都必须加上
<类型参数>
。 - 使用模板类时,要指定该模板类的参数类型。