C++:模板

模板的概念

函数重载是指在相同的函数名下,能够实现不同操作。系统根据参数的类型或参数个数的不同区分这些重载的函数。这样虽然很方便,但是出现了大量的代码冗余。该如何解决这个问题呢?
C++提供了模板。模板时类型参数化的工具。所谓类型参数化就是指把类型定义为参数,当参数实例化时,可以指定不同的数据类型,从而真正实现代码的可重用性。
模板分为函数模板和类模板,他们分别允许用户构造模板函数和模板类。如图:
C++:模板_第1张图片

函数模板与模板函数

当对每种数据类型执行相同的操作时,用函数模板来完成最为简便。只需要定义一次函数模板,根据调用函数时提供的参数类型,编译器会产生相应的目标代码函数,以正确处理每种类型的调用。
声明函数模板的格式为:

template
返回类型 函数名(模板形参表)
{
	函数体
}

例如,输出不同类型数组的元素值可定义为函数模板:

template <class T>
void PrintArrary(T* Array, int count)
{
	for (int i = 0; i < count; i++)
	{
		cout << Array[i] << " ";
	}
	cout << endl;
}
//也可以定义为
template <typename T>
void PrintArrary(T* Array, int count)
{
	for (int i = 0; i < count; i++)
	{
		cout << Array[i] << " ";
	}
	cout << endl;
}

说明:1. T是类型参数,它既可以是系统预定义的数据类型,也可以是用户自定义的类型;
2. 类型参数前需要加关键字class(或typename),这个class并不是类的意思,而是表示任何类型;
3. 在使用模板函数时,关键字class(或typename)后面的类型参数,必须实例化,即采用实际的数据类型;
4. “<>”里面的类型参数可以有一个或者多个类型参数,但多个类型参数之间要用逗号分隔。
例如:函数模板应用:输出不同类型数组的元素值。

#include 
using namespace std;
template <class T>
void PrintArrary(T* Array, int count)
{
	for (int i = 0; i < count; i++)
	{
		cout << Array[i] << " ";
	}
	cout << endl;
}

int main()
{
	int a[5] = { 1,2,3,4,5 };
	double b[7] = { 1.1,2.2,3.3,4.4,5.5,6.6,7.7 };
	char c[6] = "hello";
	PrintArrary(a, 5);
	PrintArrary(b, 7);
	PrintArrary(c, 6);
	return 0;
}

说明:从本程序可以看出,使用函数模板不用单独定义三个函数,从而解决了当采用函数重载技术时所产生的代码冗余问题。
注意:1. 在执行PrintArray函数调用时,根据参数的类型,系统自动在内存中生成一个模板函数(实例化函数),并执行该函数;
5. 函数模板中可以使用多个类型参数,但每个模板形参前必须有关键字classtypename
6. 在template语句和函数模板定义语句之间不允许有其他语句。
7. 模板函数类似于函数重载,但与函数重载不同。在进行函数重载时,每个函数体内的动作既可以相同也可以不同,但模板函数中的动作必须相同。如下面的函数只能用函数重载,而不能用模板函数。

void Print(char* name)
{
	cout << name << endl;
}
void Print(char* name, int no)
{
	cout << name << no << endl;
}
  1. 函数模板中的模板形参T可以实例化为各种类型,但实例化T的各模板实参之间必须保证类型一致,否则将发生错误。
    解决这个问题有两种方法:
    a. 采用强制类型转换。
    b. 定义一个完整的分模板函数重载函数模板。

类模板与模板类

类是对一组对象的公共性质的抽象,而类模板是更高层次的抽象。类模板(类属类或类生成类)允许用户为类定义一种模式,使类中的某些数据成员、成员函数的参数或返回值可以根据需要取任意类型。
类模板的定义格式为:

template
class 类名
{
	//```
};

说明:1. 在每个类模板定义之前,都需要在前面加上模板声明。在使用类模板时,应将它实例化为一个具体的类(模板类),类模板实例化为模板类的格式为:类名<具体类型名>
2. 模板类可以有多个模板参数;
3. 在类定义体外定义成员函数时,若该成员函数中有类型参数,则需要在函数体外进行模板声明,即在类名和函数名之间加上,格式为:返回类型 类名::成员函数名(参数表)
4. 类模板不代表一个具体的、实际的类,而是代表一类类。因此在使用时,必须将类模板实例化为一个具体的类,格式为:类名 <实际的类型> 对象名;
例如:用类模板实现栈的基本运算。

#include 
using namespace std;
const int SIZE = 100;
template <class T>
class Stack
{
public:
	Stack();
	void Push(T x);
	T Pop();
private:
	T s[SIZE];
	int top;
};

template<class T>
Stack<T>::Stack()
{
	top = -1;
}

template<class T>
void Stack<T>::Push(T x)
{
	if (top == SIZE - 1)
	{
		cout << "Stack is full" << endl;
		return;
	}
	s[++top] = x;
}

template<class T>
T Stack<T>::Pop()
{
	if (top == -1)
	{
		cout << "Stack underflow" << endl;
		return 0;
	}
	return s[top--];
}

int main()
{
	Stack<int> a;
	for (int i = 0; i < 10; i++)
	{
		a.Push(i);
	}
	for (int i = 0; i < 10; i++)
	{
		cout << a.Pop() << " ";
	}
	return 0;
}

你可能感兴趣的:(C++,c++)