模板基础
假如我们想求两个数字(整数或小数)的最大值,那么我们可以利用函数的重载来实现。
#include <iostream> using namespace std; //返回两数间的最大值 int max (int num1, int num2) { //比较num1和num2 if (num1 >= num2) { return num1; } else { return num2; } } //返回两数间的最大值 double max (double num1, double num2) { //比较num1和num2 if (num1 >= num2) { return num1; } else { return num2; } } int main() { cout << "1和3的最大值:" << max(1, 3) << endl; cout << "1.1和3.3的最大值:" << max(1.1, 3.3) << endl; return 0; }
运行结果:
这样一来,我们在使用函数max时,传入的参数可以是int型也可以是double型。同理,如果要比较string、char、float等类型的最大值,我们也可以用重载的方式。这里就不一一写出了。
但是这样很繁琐,每有一种类型就需要重载一次。如果有100多种甚至1000多种怎么办呢?重载固然可以解决,但是代码量十分巨大。
因此C++提出了模板的概念。也就是说,在写函数的时候,可以不明确具体的返回类型和参数类型。
函数模板的定义以关键字template开始,后面跟着一个参数列表。每个参数前面必须加typename或class,即<typename typrParameter>或<class typrParameter>。
具体的例子见下:
#include <iostream> using namespace std; //定义一个模板T template <typename T> //也可以是template <class T>,但是class可能会与类的概念混淆,所以推荐使用typename //返回两数间的最大值 //该函数的返回类型为T,两个参数类型也为T,也就是说,这三个的类型是一样的 T maxValue (T value1, T value2) { if (value1 >= value2) { return value1; } else { return value2; } } int main() { cout << "1和3的最大值:" << maxValue(1, 3) << endl; cout << "1.1和3.3的最大值:" << maxValue(1.1, 3.3) << endl; cout << "C字符串NBC和C字符串ABC的最大值:" << maxValue("ABC", "NBC") << endl; cout << "字符串NBC和字符串ABC的最大值:" << maxValue(string("ABC"), string("NBC")) << endl; return 0; }
先来看一下运行结果:
为什么第三行最大值的结果是ABC而不是NBC呢?
因为对于maxValue("ABC", "NBC")来说,里面参数是C字符串,C字符串可以看成一个数组,而两个数组名就代表着两个地址。所以这个函数比较的实际是两个地址而不是里面的值。因此我们可以使用string()的构造方法来构造字符串,这样一来就比较的是两个字符串。
模板类
同理,一个类也可以设置为模板类。看下面的例子:
#include <iostream> using namespace std; //定义一个模板T template<typename T> class MaxValue { public: MaxValue(T value1, T value2){ this->value1 = value1; this->value2 = value2; } T getMaxValue(){ if (this->value1 >= this->value2) { return value1; } else { return value2; } } private: T value1; T value2; }; int main() { MaxValue<int> m1(1,3); cout << "1和3的最大值:" << m1.getMaxValue() << endl; MaxValue<string> m2("ABC","NBC"); cout << "字符串NBC和字符串ABC的最大值:" << m2.getMaxValue() << endl; return 0; }
这里为了方便,没有实现类和main函数的分离。但是要注意,对于模板类有以下几个注意的地方:
- 模板类的类定义和类实现不分离。因为有的编译器不支持模板类定义和实现的分离。
- C++允许模板类指定一个默认的类型,如:template<typename T = int>将默认类型设置为int
- 每一次的实现前都要加template<typename T>
- 作用域解析运算符 ::前面不再是ClassName,而是ClassName<T>。比如上面的构造函数的实现为:
template<typename T> MaxValue<T>::MaxValue(T value1, T value2){ this->value1 = value1; this->value2 = value2; }