函数模板与类模板定义和使用

模板是将具有相似性的类和函数归纳起来构成一个类族或函数族,它可是程序具有通用性。模板分为类模板和函数模板。


目录

(一)函数模板

一般定义形式

模板函数重载

函数模板参数

带有多类型参数的函数模板

(二)类模板

类模板的使用


(一)函数模板

int max(int a,int b);
float max(float a,float b);
double max(double a,double b);

如上这三个重载函数,他们的操作相同,都是求两个数中的最大值。为了避免逐个定义重载函数的繁琐编程,由于函数模板使用通用数据类型定义函数,因此使用函数模板完成这项工作更为简洁和方便

一般定义形式

template        //template函数模板关键字;T为通用数据类型
返回类型 FunctionName(数据参数表)     //FunctionName函数模板名
{
    函数模板定义体;                  //接上,T可为基本数据类型或类类型,需加前缀class和typename
}

例如对之前的三个重载函数进行模板化,为:

template
T max(T a,T b)
{
    return a>b?a:b;    //T作为返回类型和参数类型
}

函数模板只是函数的描述,表示它每次能单独处理类型形参表中说明的数据类型。它不是一个实实在在的函数,是以具体类型为实参来生成函数体的模板,编译系统不为其产生任何执行代码。使用函数模板可以根据特定的数据类型,产生一个该模板的实例,该函数可以像普通函数一样调用。

#include 

using namespace std;

template
T abs(T n)
{
	return (n<0)?-n:n;
}

int main()
{
	int int1 = 5;
	int int2 = -6;
	long lon1 = 70000L;
	long lon2 = -80000L;
	double dub1 = 9.95;
	double dub2 = -10.15;

	//模板函数的实例化
	cout<<"\nabs("<
	cout<<"\nabs("<
	cout<<"\nabs("<
	cout<<"\nabs("<
	cout<<"\nabs("<
	cout<<"\nabs("<
	cout<

模板函数重载

在编译程序时,输入参数的类型与重载函数的参数类型隐式转换后一致时,调用重载函数,否则调用模板函数(由于博客和书的结论不太一样,并且不知道该听谁的,于是。。。自己总结了)

#include
using namespace std;

template
T Max(T a, T b) {
	cout << "\nT Max(T a,T b)" << endl;
	return a > b ? a : b;
}

int Max(int a, int b) {
	cout << "\nint Max(int a,int b)" << endl;
	return a > b ? a : b;
}

template
T Max(T a, T b,T c) {
	cout << "\nT Max(T a,T b,T c)" << endl;
	return Max(Max(a, b), c);
}
int main() {
	int a = 1;
	int b = 2;
	cout << Max(a, b) << endl;           //当函数模板和普通函数模板都符合时,优先选择普通函数
	cout << Max<>(a, b) << endl;         //若显示使用函数模板,则使用<>类型列表
	cout << Max(3.0, 4.0) << endl;       //如果函数模板可以产生一个更好的匹配,则选择模板
	cout << Max(5.0, 6.0, 7.0) << endl;  //重载
	cout << Max('a', 100) << endl;       //调用普通函数可以隐式类型转换
	return 0;
}

结果
int Max(int a,int b)
2

T Max(T a,T b)
2

T Max(T a,T b)
4

T Max(T a,T b,T c)

T Max(T a,T b)

T Max(T a,T b)
7

int Max(int a,int b)
100
请按任意键继续. . .

函数模板参数

函数模板中的数据形参分为:

(1)引用型参数:可提高参数传递效率。

  • 一般引用型参数:templateT max(T &a,T &b);      函数执行过程中,其数据形参的改变会影响数据实参的改变。
  • 常量引用型参数:templateT max(const T &a,const T &b);        引用型参数前用 const 限定,最常使用(考虑参数传递效率和安全性)。

(2)非引用型参数: templateT max(T a,T b);

带有多类型参数的函数模板

形式如下:

template
[return-type] function_name(T1 param1,T2 param2...);
//return-type 为返回类型,既可以是一个具体的类型,也可以是 T1、T2中的通用数据类型。

Template
TRetun max(TArg a,TArg b)
{
    return a > b ? a : b;
}
#include 

using namespace std;

template void display(T1 x,T2 y)
{
	cout<

(二)类模板

使用模板生成对象时自动创建该模板的一个实例——模板类,也可以显式声明模板类。模板类主要用于容器类,这些类可以包含以特定方式组织起来的给定类型的对象集。例如数组、堆栈、链表,他们所使用的存储方式独立于操作对象的类型。类模板提供的工具,可以定义存储任意类型的对象的容器,模板的参数可用于指定容器存储的对象类型。

类模板定义及实现的一般形式如下:

template<类型形式参数表> class className
{
    //类声明体
};
template<类型形式参数表>
返回类型className<类型名表>::MemberFuncName1(形式参数表)
{
    //成员函数定义体
}
...
template<类型形式参数表>
返回类型className<类型名表>::MemberFuncNameN(形式参数表)
{
    //成员函数定义体
}

定义和实现一个单向链表的模板类:

//list.h
#include 
using namespace std;

template class List
{
public:
	List();
	void Add(T&);					//添加结点
	void Remove(T&);				//删除结点
	T* Find(T&);					//查找结点
	void PrintList();				//打印链表
	~List();
protected:
	struct Node						//结构结点
	{
		Node* pNext;
		T* pT;
	};
	Node *pFirst;					//链首节点指针
};

templateList::List()
{
	pFirst = 0;
}

template void List::Add(T& t)	//头插法
{
	Node* temp = new Node;			//从堆空间中申请一个结点
	temp->pT = &t;					//将T对象挂载在这个节点上
	temp->pNext = pFirst;			//将该结点指向链首的结点
	pFirst = temp;					//将该节点成为链首
}

template void List::Remove(T& t)
{
	Node* q = 0;					//用来点位待删除的结点
	if(*(pFirst->pT)==t)			//T类中==需有定义
	{
		q = pFirst;
		pFirst = pFirst -> pNext;	//带删除结点在链首时的脱链
	}
	else
	{
		for(Node* p = pFirst; p -> pNext; p = p -> pNext)
		{
			if(*(p -> pNext -> pT) == t)
			{
				q = p -> pNext;
				p -> pNext = q -> pNext;	
				break;
			}
		}
	}
	if(q)
	{
		delete q -> pT;				//删除节点上的T类对象
		delete q;					//删除结点
	}
}

template T* List::Find(T& t)
{
	for(Node* p = pFirst; p; p = p -> pNext)
		if(*(p -> pT) == t)
			return p -> pT;
	return 0;
}

template void List::PrintList()
{
	for(Node* p = pFirst; p; p = p -> pNext)
		cout<<*(p -> pT)<<" ";
	cout< List::~List()
{
	Node *p;
	while( p = pFirst )
	{
		pFirst = pFirst -> pNext;
		delete p -> pT;
		delete p;
	}
	pFirst = 0;
}

类模板的使用

类模板实例创建方式

className<类型实参表> object;

使用实例

// singleList.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include 
#include "list.h"
using namespace std;

int main()
{
	//创建模板类List和该对象
	List floatList;
	//创建和遍历浮点链表
	for(int i = 1; i < 7; i ++)
		floatList.Add(*new float(i + 0.6));
	floatList.PrintList();
	//查找并删除结点
	float b = 3.6;
	float* pa = floatList.Find(b);
	if(pa)
		floatList.Remove(*pa);
	floatList.PrintList();

	return 0;
}

结果
6.6 5.6 4.6 3.6 2.6 1.6
6.6 5.6 4.6 2.6 1.6
请按任意键继续. . .

 

你可能感兴趣的:(C++,函数模板,类模板,模板函数重载,函数模板参数,多类型参数的函数模板)