《程序设计与数据结构》——什么是类?
RangeValidator类是在编译时定义的,而rangeValidator对象是在运行时作为类的实例创建的。宏展开后如下:
RangeValidator rangeValidator = {{validateRange}, (0), (9)};
其相当于:
rangeValidator.validate = validateRange;
rangeValidator.min = 0;
rangeValidator.max = 9;
如果有以下定义:
void * pValidator = &rangeValidator;
即可通过pValidator引用RangeValidator的min和max。校验函数的调用方式如下:
(RangeValidator *)pValidator -> validate(pValidator, 8);
以上调用形式的前提是已知pValidator指向了确定的结构体类型,如果pValidator将指向未知的校验器,显然以上调用形式无法做到通用,那么如何调用?
虽然pValidator与&rangeValidator.validate的类型不一样,但它们的值相等,因此可以利用这一特性获取validateRange()函数的地址。即:
Validate validate = *((Validate *)pValidator);
其调用形式如下:
validate(pValidator, 8);
根据OCP开闭原则,由于不允许修改push()函数,因此需要编写一个通用的扩展push功能的pushWithValidate()函数,详见程序清单 4.7。
程序清单 4.7 pushWithValidate()
1 bool pushWithValidate(stackADT stack, void *pValidator, int value)
2 {
3 Validate validate = *((Validate*)pValidator);
4 if (pValidator && !validate(pValidator, value)){
5 return false;
6 }
7 return push(stack, value);
8 }
其中,stack是指向当前对象(栈)的指针,用于请求对象对自身执行某些操作,而结构体的成员变量就是通过stack指针找到自己所属的对象的。pValidator为指向校验器的指针,如果无需校验,则将pValidator置NULL并返回true。
使用validator.h接口的通用校验器范例程序详见程序清单 4.8。
程序清单 4.8 通用校验器使用范例程序
1 #include
2 #include"Stack.h"
3 #include"validator.h"
4 // 添加pushWithValidate()函数
5 int main(int argc, int *argv[])
6 {
7 stackADT stack;
8 int temp;
9
10 stack = newStack();
11 RangeValidator rangeValidator = newRangeValidator(0, 9);
12 for (int i = 0; i < 16; i ++){
13 pushWithValidate(stack, &rangeValidator, i);
14 }
15 while (!stackIsEmpty(stack)) {
16 pop(stack, &temp);
17 printf("%d ", temp);
18 }
19 printf("\n");
20 OddEvenValidator oddEvenValidator = newOddEvenValidator(true);
21 for (int i = 0; i<16; i++){
22 pushWithValidate(stack, &oddEvenValidator, i);
23 }
24 while (!stackIsEmpty(stack)) {
25 pop(stack, &temp);
26
周立功 相关文章:
- 电源软启动的实用设计技巧(07-16)
- 周立功:动态分布内存——malloc()函数与calloc()函数(07-22)
- 周立功“程序设计与数据结构”:深度解剖动态分布内存的free()函数与realloc()函数(07-25)
- 周立功教你学程序设计技术:做好软件模块的分层设计,回调函数要这样写(07-30)
- 周立功教你学C语言编程:教你数组是如何保存指针的(07-31)
- 算法的泛化问题,这些坑你可能都经历过!|周立功教你学软件设计(08-01)