前言
我们都知道在c++与c语言的区别中,最大的不同就是c++訲多了对象和模板,前面我们介绍了面向对象的编程,现在我们来认识一下c++中模板的知识。
模板八函数或类要处理的数据类型参数化,即表现为数据的多态性。在面向对象技术中,模板是另一种代码重用机制。
提示:以下是本篇文章正文内容,下面案例可供参考
一、模板的概念
强类型的严格性和灵活性
在强类型程序设计语言中,参与运算的所有对象的类型在编译时即可确定下来,并且编译程序将进行严格的类型检查,这样就可以在程序未运行之前就检查出类型不兼容的错误。
但是由于这种强类型语言在提高程序的可靠性的同时又带来了一些负作用。
例如我们在使用函数求某一个计算类容的时候,会出现参数类型不一样,他们的算法相同,但是参数不同,所以程序员就必须写两个程序。这就不利于程序的扩展和维护。
解决冲突的路径
如何解决强类型的严格性与灵活性的冲突?以往有三种方法。
第一种:利用宏函数,使用宏函数虽然确实会简便问题,但是我们知道引入宏函数后可能会导致程序出现以些意想不到的问题。所以在c++中一般不会使用宏函数。
第二种:为各种类型重载这一函数,但是重载函数又显得麻烦。增加工作量。
第三种:放松类型检查,在编译期间忽略这些类型的匹配问题。而在运行期间进行类型匹配检查,但是在程序运行的时候可能会出现类型不兼容的错误。
综和上面的方法,我们发现无论何种方法,都会有漏洞,那么最理想的方法是什么?最理想的方法是直接将数据类型作为类的参数,就像函数可以将数据作为参数一样。这种机制叫做“类属”(genericity),强类型程序设计语言(如Ada,Eiffel等语言)通常都采用这种方式
模板的概念
模板是一种参数化多态性的工具,可以为逻辑功能相同而类型不同的程序提供代码共享的机制。
由于c+程序结构的主要构件是类和函数,所以在c++中,模板被分为函数模板和类模板。模板并非一个实实在在的函数或类,仅仅是函数或类的描述,模板运算对象的类型不是实际的数据类型,而是一种参数化的类型(又称为类属类型)。带类属参数的函数叫做函数模板,带类属参数的类叫做类模板。
一(1).函数模板
通常,设计的算法是可以处理多种数据类型的,c++提供的函数模板可以一次定义出具有共性(除类型参数外,其余全相同)的一组函数,同时也可以处理多种不同类型数据的函数。从而大大增强了函数设计的通用性。
函数模板的定义
函数模板定义的格式:
template<模板参数表>
<返回值类型><函数名>(<参数表>)
{
<函数体>
}
其中,关键字template是定义模板的关键字,<模板参数列表>中包含一个或多个用逗号分开的模板参数项,每一项又保留字class或者typename开始,后跟用户命名的标识符,此标识符为模板参数,表示数据类型。函数模板中可以利用这些模板参数定义函数返回值类型,参数类型和函数体中的变量类型。它同基本数据类型一样,可以在函数中的任何地方使用。
函数模板的实例化
#include<iostream> #include<string> using namespace std; template <typename T> //函数模板; T Max(T a, T b) { return a > b ? a : b; } int main() { int a, b; cout << "Input two integers to a&b:" << endl; cin >> a >> b; cout << "max(" << a << "," << b << ")=" << Max(a, b) << endl; //有些编译软件不能使用max模板函数,是由于系统自带max函数; char c, d; cout << "Input two chars to c&d:" << endl; cin >> c >> d; cout << "max(" << "\'" << c << "\'" << "," << "\'" << d << "\'" << ")="; cout<< Max(c, d) << endl; float x, y; cin >> x >> y; cout << "Input two float x&y:" <<endl; cout << "max(" << x << "," << y << ")=" << Max(x, y) << endl; cout << "Input two string to p&h:" << endl; string p, h; cin >> p >> h; cout << "max(" << "\"" << p << "\"" << "," <<"\"" << h <<"\"" << ")="; cout << Max(p, h) << endl; return 0; }
在程序中,我们可以发现在使用相同的函数时,不再需要多次定义数据类型,编译器会根据语句中的实际数据类型而产生相应的函数。
这就极大的减轻了程序员的工作负担。
下面我们来看看他的图示:
函数模板的声明和定义必须是全局作用域,而且模板不能被声明成类的成员函数。
函数模板的重载
函数模板有多种重载方式,可以定义同名的函数模板,提供不同的参数和实现;也可以用其他非模板函数重载。
1.函数模板的重载
重载函数模板和重载函数类似,重载函数模板便于定义类属参数,或者函数参数的类型。个数不同所进行的操作。
#include<iostream> using namespace std; template <typename T> T Max(T a, T b) { return a > b ? a : b; } //重载; template<typename T> T Max(T a[], T n) { T temp; temp = a[0]; for (int i = 0; i < n; i++) { if (temp < a[i]) temp = a[i]; } return temp; } int main() { int a, b; cout << "Input two integers to a&b" << endl; cin >> a >> b; cout << "Max(" << a << "," << b << ")=" << Max(a, b) << endl; int i, aa[10] = { 3,7,9,11,0,6,7,5,4,2 }; cout << "The original array:" << endl; for (i = 0; i < 10; i++) { cout << aa[i] << ","; } cout << endl; cout << "Max of 10 integers is" << Max(aa, 10) << endl; return 0; }
2.用普通函数重载函数模板
函数模板实例化时,实际参数类型将替换模板参数,虽然这种参数替换具有类型检查功能,但是却没有普通传值参数的类型转换机制。
也就是说,函数模板没办法预知隐式的类型转换。这个时候我们就可以用非模板函数重载一个同名的函数模板;
#include<iostream> using namespace std; template <typename T> T Max(T a,T b) { return a > b ? a : b; } int Max(int a, float b) //用普通函数重载函数模板; { return a > b ? a : b; } int main() { char a = '4', b = '5'; float c = 5.7; int d = 10; cout<<Max(a, b) << endl; cout << Max(d, c) << endl; return 0; }
3.用特定函数重载函数模板
#include<iostream> #include<cstring> using namespace std; template <typename T> T Max(T a, T b) { return a > b ? a : b; } int Max(int a, float b) { return a > b ? a : b; } char* Max(char* a,char* b) { return strcmp(a, b) > 0 ? a : b; } int main() { char a = '4', b = '5'; int c = 5; cout << "Max(" << "\'" << a << "\'" << "," << "\'" <<b << "\'" << ")="; cout << Max(a, b) << endl; cout << "Max(" << "\'" << a << "\'" << "," << "\'" << c << "\'" << ")=" << Max(a, c) << endl; const char* p, * h; p = "qaz"; h = "wsx"; cout << "Max(" << "\"" << p << "\"" << "," << "\"" << h << "\"" << ")=" << Max(p,h) << endl; }
类模板
同函数模板一样,使用类模板可以为类定义一种模式,使得类中的某些数据成员。某些成员函数的参数以及某些成员函数的返回值能取任意类型。类模板是对一批仅有成员数据类型不同类的抽象,程序员只要为这一批类所组成的整个类家族创建一个类模板,然后给出一套程序代码,就可以用来生成多种具体的类,即模板类。