模板
为了代码重用,代码就必须是通用的;通用的代码就必须不受数据类型的限制。那么我们可以把数据类型改为一个设计参数。这种类型的程序设计称为参数化(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;
}