函数模板和类模板

模板

为了代码重用,代码就必须是通用的;通用的代码就必须不受数据类型的限制。那么我们可以把数据类型改为一个设计参数。这种类型的程序设计称为参数化(parameterize) 程序设计。软件模块由模板(template) 构造。包括函数模板(function template)和类模板(class template)。

1 函数模板

函数模板可以用来创建一个通用功能的函数,以支持多种不同形参,简化重载函数的设计。函数模板定义如下:
template<模板参数表>
返回类型 函数名(形式参数表)
{……;} //函数体
<模板参数表>(template parameter list)尖括号中不能为空,参数可以有多个,用逗号分开。模板参数主要是模板类型参数。
模板类型参数(template type parameter)代表一种类型,由关键字 class 或 typename(建议用typename ) 后加一个标识符构成,在这里两个关键字的意义相同,它们表示后面的参数名代表一个潜在的内置或用户定义的类型。、

template<typename t>
t max(t a, t b)
{
	return a > b ? a : b;
}

int main()
{
	int a = 0;
	// 模板参数列表中只有一种数据类型,传入的实参也只有一种数据类型
	// 可以直接由函数模板生成模板函数
	a = max(1, 2);
	
	// 模板参数列表中只有一种数据类型,但是此时传入的实参有两种数据类型
	// 在调用时需要强制的类型转换,保证实参的类型个数与模板参数列表的类型个数一致
	// 由函数模板生成模板函数时编译器不能做到自动的隐式转换,需要显示的强制转换
	a = max(1, (int)2.0);
	a = max((double)1, 2.0);
	
	// 显示转换也可以以尖括号形式的语法进行转换
	a = max<int>(1, 2.0);
	a = max<double>(1, 2.0);
}

2 类模板

类模板定义如下:
template<类型模板或参数表>
class 类名{
…… //类声明体
}; //再次指出分号不可少

模板中的成员函数在类外实现时需要写成函数模板

template<模板参数表>
返回类型 类名<类型模板或参数表>::成员函数名1(形参表) {
……;//成员函数定义体
}
……
template<模板参数表>
返回类型 类名<类型模板或参数表>::成员函数名n(形参表) {
……;//成员函数n定义体
}

模板参数有两种:模板类型参数和模板非类型参数。
模板非类型参数由一个普通的参数声明构成。表示该参数名代表了一个潜在的常量,企图修改这种参数的值是一个错误。如数组类模板,可以有一个数组长度的非类型参数:

template< typename T,int N>
class array
{
	T vector[N]; 
	int size;
public:
	array():size(N){}
};

从通用的类模板定义中生成类的过程称为模板实例化(template instantiation),其格式为:
类名<类模板实在参数表> 对象名;
在类外定义的类模板中的成员函数必须是函数模板。这样的成员函数只有在被调用(或取地址)时才被实例化。成员函数模板定义中,指定成员函数所在类域的类型名后跟的<模板参数名表>中成员,与类模板的<模板参数表>中的类型参数名相同,但不加 typename 或class。

类模板实现单链表

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
using namespace std;

// 会将链表类声明为节点类的友元类,在此做一个前向声明
template<typename type>
class List;

template<typename type>
class ListNode
{
	// 将链表类声明为友元类,操作链表时会访问节点类的指针域和数据域
	friend class List<type>;
public:
	// type() 类模板的零初始化,当传入具体的类型时,相当于int() char()
	// int a = int()  a 初始化为0 语法上是正确的
	ListNode() :data(type()), next(NULL)
	{

	}
	ListNode(type d, ListNode<type> *p = NULL) :data(d), next(p)
	{
		
	}
	~ListNode()
	{

	}
private:
	type data;
	ListNode<type> *next;
};

template<typename type>
class List
{

public:
	List();
	bool PushBack(type x);
	void PrintList()const;
private:
	ListNode<type> *first;
	ListNode<type> *last;
	size_t size;
};

// 类模板的成员函数类外实现,需要写成函数模板
template<typename type>
List<type>::List()
{
	// 构造函数做头结点的申请与初始化工作
	first = last = (ListNode<type>*)malloc(sizeof(ListNode<type>));
	last->next = NULL;
	size = 0;
}

template<typename type>
bool List<type>::PushBack(type x)
{
	ListNode<type> *tmp = (ListNode<type>*)malloc(sizeof(ListNode<type>));
	if (tmp == NULL)
		return false;
	tmp->data = x;
	tmp->next = NULL;

	last->next = tmp;
	last = tmp;
	size++;
	return true;
}

template<typename type>
void List<type>::PrintList()const
{
	ListNode<type> *p = first->next;
	while (p != NULL)
	{
		cout << p->data << "-->";
		p = p->next;
	}
	cout << "Null." << endl;
}

int main()
{
	List<int> intList;
	List<char> charList;

	for (int i = 0; i <= 10; i++)
	{
		intList.PushBack(i);
	}
	intList.PrintList();

	for (int i = 'a'; i <= 'h'; i++)
	{
		charList.PushBack(i);
	}
	charList.PrintList();

	system("pause");
	return 0;
}







  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值