Lecture 19 泛型(类属)程序设计
面临的问题
在程序设计中,经常需要用到一些功能完全相同的程序实体,但它们所涉及的数据的类型不同。
例如,对不同元素类型的数组进行排序的函数:
void int_sort(int x[],int num);
void double_sort(double x[],int num);
void A_sort(A x[],int num);
这三个函数的实现是一样的(如都采用快速排序算法)。
再例如,元素类型不同的栈类:
class IntStack
{
int buf[100];
public:
void push(int);
void pop(int&);
};
class DoubleStack
{
double buf[100];
public:
void push(double);
void pop(double&);
};
class AStack
{
A buf[100];
public:
void push(A);
void pop(A&);
};
这三个类的实现也是一样的(用数组表示元素)。
对于前面的三个排序函数和三个栈类,如果能分别只用一个函数和一个类来描述它们,这将会大大简化程序设计的工作!
以上需求可以用“泛型”来解决。
泛型(类属)
一个程序实体能对多种类型的数据进行操作或描述的特性称为类属或泛型(Generics)。
具有类属特性的程序实体通常有:
-
类属函数:一个能对不同类型的数据完成相同操作的函数。
-
类属类:一个成员类型可变、但功能不变的类。
基于具有类属性的程序实体进行程序设计的技术称为:泛型程序设计(或类属程序设计,Generic Programming)。
类属函数
类属函数是指一个函数能对不同类型的参数完成相同的操作。
C++提供了两种实现类属函数的机制:
-
采用通用指针类型的参数(C语言的做法)
-
函数模板
用通用指针参数实现类属排序函数
函数定义:
void sort(void *base, //需排序的数据(数组)内存首地址
unsigned int count, //数据元素的个数
unsigned int element_size, //一个数据元素所占内存大小(字节数)
int (*cmp)(const void *, const void *) ) //比较两个元素的函数
{
//不论采用何种排序算法,一般都需要对数组进行以下操作:
//取第i个元素
(char *)base+i*element_size
//比较第i个和第j个元素的大小 (利用调用者提供的回调函数cmp实现)
(*cmp)((char *)base+i*element_size,
(char *)base+j*element_size)
//交换第i个和第j个元素的位置
char *p1=(char *)base+i*element_size,
*p2=(char *)base+j*element_size;
for (int k=0; k<element_size; k++)
{
char temp=p1[k]; p1[k] = p2[k]; p2[k] = temp;
}
} //上面的char用byte替代更好:typedef unsigned char byte;
类属排序函数的使用
int int_compare(const void *p1, const void *p2)
//比较int类型元素大小。
{
if (*(int *)p1 < *(int *)p2)
return –1;
else if (*(int *)p1 > *(int *)p2)
return 1;
else
return 0;
}
......
int a[100];
......
sort(a,100,sizeof(int),int_compare)