什么是函数模板以及什么是类模板

【1】模板的含义

(1) 模板就是实现代码重用的机制的一种工具,它可以实现类型参数化,即把类型定义为参数,从而实现了真正的代码可重用性。
(2) 模板可以分为两类,一个是函数模板,另外一个是类模板。

【2什么是函数模板?

所谓函数模板,实际上就是建立一个通用的函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来代替。而这个通用的类型就称为函数模板。
注:
1:凡是函数体相同的函数都可以用这个模板来代替,不必定义多个函数,只需在模板中定义一次即可
2:在调用函数时,系统会根据实参的类型来取代模板中的虚拟类型,从而实现不同类型的函数功能
定义函数模板的一般形式为
template<typename T>或
template<class T>
tempale的含义是“模板”,尖括号中先写关键字typename(或class),后面跟一个类型参数T,这个类型参数T
就是一个虚拟的类型名。它表示模板中出现的T是一个类型名,但是现在并没有指定它是哪一种具体的类型。
注:函数模板的参数可以使多个。例如
template<class T1 ,typename T2>

【3】函数模板的一个简单demo

#include<iostream>
#include<Windows.h>
using namespace std;

template<typename T>		//模板声明,其中T为类型参数
T Max(T a ,T b,T c)			//定义一个通用的函数,用T作为虚拟的类型名
{
	if(b>a)a=b;
	if(c>a)a=c;
	return a;
}
int main()					//主函数,控制台从这里开始运行程序
{
	int i1=185,i2=-76,i3=567,i;					//定义四个整形变量
	double d1=56.87,d2=90.23,d3=-3214.78,d;		//定义四个双精度浮点型变量;
	i=Max(i1,i2,i3);							//第一次调用函数模板,实参类型为整形;
	cout<<"The max is:"<<i<<endl;
	d=Max(d1,d2,d3);							//第二次调用函数模板,实参类型为双精度浮点型
	cout<<"The max is:"<<d<<endl;
	system("pause");
	return 0;
}

【4什么是类模板?

C++的类模板为生成通用的类声明提供了一种更好的方法,模板提供参数化类型,即能够将类型名作为参数传递给接收方来建立类或函数。
以下面的Stack类为基础来建立模板:
typedef unsigned long Item;

class Stack
{
private:
	enum{MAX=10};
	Item items[MAX];
	int top;
public:
	stack();//默认的构造函数
	bool isempty();//判空
	bool isfull();//盘满
	bool push(const Type& item);//进栈
	bool top(type & item);//出栈,将栈顶元素放在item中
}
采用模板时,将使用模板定义替换Stack声明,使用模板成员函数替换Stack的成员函数,和模板函数一样,模板类以下面这样的代码开头:
template<class Type>
关键字template告诉编译器,将要定义一个模板,尖括号的内容相当于函数的参数列表,可以把关键字class看作是变量的类型名,该变量接收类型作为其值,把Type看作是该变量的名称。
这里使用class并不是代表Type的类型必须为一个类;而只是表明Type是一个通用的类型说明符,在使用模板时,将使用实际的类型替换它(指Type),较新版本的C++实现允许在这样情况下使用不太容易混淆的关键字typename代替class。
template<typename Type>
可以使用自己的泛型名代替Type,其命名规则和其它标识符相同,当前流行的选项包括T和Type,我将使用后者。当模板被调用时,Type将被具体的类型值(如int或double)取代。在模板定义中,可以使用泛型名来标识要存储在栈中的类型。对于Stack来说,这意味要将所有的typedef标识符Item替换为Type。例如,
Item item[MAX];
应改为:
Type item[Max];
同样,可以使用模板成员函数替换所有类的方法,每个函数都以相同的模板声明打头:
template <class Type>
同样应使用泛型名Type替换typedef标识符Item。另外,还需要将类限定符从Stack::改为Stack<Type>::
例如,
bool Stack::push(const Item&item)
{
 ...
}
应改为:
template <class Type>
bool Stack<Type>::push(const Item & item)
{
	...
}
如果在类声明中定义了方法(内联定义),则可以省略模板的前缀和类限定符
【5】类模板的创建

下面示例程序列出了类模版 和成员函数模板
注:
不能将模版成员函数放在独立的实现文件中。由于模板不是函数,所以他们不能单独编译,模板必须与特定的模板实例化请求一起使用,为此,最简单的方法是将所有的模板信息放在一个头文件中,并在要使用这些模板的文件中包含该头文件
#ifndef STACKTP_H_
#define STACKTP_H_
template <class Type>       //类模板定义开始
class Stack
{
private:
	enum{MAX=10};
	Type items[MAX];
	int top;
public:
	Stack();//默认构造函数
	bool isempty();
	bool isfull();
	bool push(const Type & item);
	bool pop(Type & item);
};

template <class Type>		//类中的成员函数模板定义开始
Stack<Type>::Stack()
{
	top=0;
}

template<class Type>
bool Stack<Type>::isempty()
{
	return top==0;
}

template<class Type>
bool Stack<Type>::isfull()
{
	return top==MAX;
}

template<class Type>
bool Stack<Type>::push(const Type & item)
{
	if(top<MAX)
	{
		items[top++]=item;
		return true;
	}
	else 
		return false;
}

template<class Type>
bool Stack<Type>::pop(Type &item)
{
	if(top>0)
	{
		item=item[top--];
		return true;
	}
	else
		return false;
}
#endif
【6】模板类的使用
仅在程序中包含模板并不能生成模板,而必须请求实例化,从而需要声明一个为模板类的对象,做法是:使用所需的具体类型替换泛型名,实例如下:
Stack<int> kernels; //实例化了一个用于存储int型数据的类
Stack<string> colonels; //实例化了一个用于存储String型数据的类
经上述声明,编译器将按Stack<Type>模板类声明两个独立的类声明和两组独立的类方法。类声明Stack<int>将使用int替换模板中所有的Type,而声明Stack<string>将使用String替换模板中所有的Type。
泛型标识符———— 例如这里的Type————成为类型参数,这意味着他们类似于变量,但是赋给他们的不能是数字,而必须是类型,因此在kernels声明中,类型参数Type的值为int。
注意必须显示地提供所需类型,这与常规的函数模板是不同的,因为编译器可以根据函数的参数类型来确定要生成那种函数。
【7】函数模板的一个简单demo
#include<iostream>
#include<string>
#include<cctype>
#include"Stack.h"
using namespace std;

int main()
{
	Stack<std::string>st;//利用模板类Stack实例化了一个空桟st,存储类型为String
	char ch;
	std::string po;
	cout<<"Please enter A to add a purchase order,\n"<<"p to process a PO,or Q to quit.\n";
	while(cin>>ch&&std::toupper(ch)!='Q')
	{
		while(cin.get()!='\n')
		{
			continue;
		}
		if(!std::isalpha(ch))
		{
			cout<<'\a';
			continue;
		}
		switch(ch)
		{
		case 'A':
		case 'a':cout<<"enter a PO number to add: ";
			cin>>po;
			if(st.isfull())
				cout<<"stack already full\n";
			else st.push(po);
			break;
		case 'P':
		case 'p':if(st.isempty())
					 cout<<"stack already empty\n";
				 else{
				 st.pop(po);
				 cout<<"PO#"<<po<<"popped\n";
				 break;
				 }
		}
		cout<<"Please enter A to add a purchase order,\n"<<"p to process a PO,or Q to quit.\n";
	}
    cout<<"Bey\n";
	return 0;
}



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值