先看看困惑来来源:
这让我很疑惑,难道c也支持“多态”的特性么?貌似没见过呀~
google帮忙,明白了一二,特此记录:
原来这种“多态”是通过c语言的可变长参数实现的(python也具有这种特性)
有关可变长参数的介绍见文章末尾的参考列表,说的很详细。
截取关键的内容:
1.可变长参数的宏定义:
(学习宏函数的典例呀)
// stdarg.h #define va_start _crt_va_start #define va_arg _crt_va_arg #define va_end _crt_va_end // vadefs.h typedef char * va_list; #define _crt_va_start(ap,v) ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) ) #define _crt_va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) #define _crt_va_end(ap) ( ap = (va_list)0 ) #define _ADDRESSOF(v) ( &(v) ) #define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
C语言可变参数通过三个宏(va_start、va_end、va_arg)和一个类型(va_list)实现, void va_start ( va_list ap, paramN ); 参数: ap: 可变参数列表地址 paramN: 确定的参数 功能:初始化可变参数列表(把函数在 paramN 之后的参数地址放到 ap 中)。 void va_end ( va_list ap ); 功能:关闭初始化列表(将 ap 置空)。 type va_arg ( va_list ap, type ); 功能:返回下一个参数的值。 va_list :存储参数的类型信息。 好了,综合上面3个宏和一个类型可以猜出如何实现C语言可变长参数函数:用 va_start 获取参数列表(的地址)存储到 ap 中,用 va_arg 逐个获取值,最后用 va_arg 将 ap 置空。
按照说明,我实现了一个简单的测试代码,来测试可变长参数:
/************************************************************************* * @File Name: test.c * @Author: kehr * @Mail: [email protected] * @Created Time: 2013年11月30日 星期六 19时06分32秒 * @Copyright: GPL 2.0 applies * @Purpose: 测试可变长参数,实现c的“多态” *************************************************************************/ #include <stdio.h> #include <stdarg.h> void show(int first_param,int flag, ...); int main() { show(1,2,3,4,5); return 0; } void show(int first_param,int flag, ...) { //定义参数列表 va_list vl; //初始化参数列表 va_start (vl, flag); //获取参数值 printf ("%d ",first_param); printf ("%d ",flag ); printf("%d ",va_arg(vl,int)); printf("%d ",va_arg(vl,int)); printf("%d ",va_arg(vl,int)); printf("\n"); //关闭参数列表 va_end(vl); }
/************************************************************************* * @File Name: test.c * @Author: kehr * @Mail: [email protected] * @Created Time: 2013年11月30日 星期六 19时06分32秒 * @Copyright: GPL 2.0 applies * @Purpose: 测试可变长参数,实现c的“多态” *************************************************************************/ #include <stdio.h> #include <stdarg.h> #define _NAME 0 #define _NAME_AGE 1 void show(int first_param,int flag, ...); //对外暴露的接口 void showName(char* name); //内部的实现 void showNameAndAge(char* name, int age); //内部的实现 int main() { //如果不看show的具体实现,那么下面这两句代码不就是“多态”了么? show(1,_NAME,"xiaogqiang"); show(2,_NAME_AGE,"xiaoqiang",23); return 0; } void show(int first_param,int flag, ...) { //这里地一个参数没有做处理,完全可以直接输出,或进行其它处理 printf("%d\n",first_param); //定义参数列表 va_list vl; //需要处理的参数 char* name; int age; //初始化参数列表 va_start (vl, flag); //获取参数值 //printf("flag=%d\n",flag); //printf("name=%s\n",va_arg(vl,char*)); //printf("age=%d\n",va_arg(vl,int)); //单独使用下面这条语句无法得到结果,猜测是printf的内部原因。 //printf("name=%s\n age=%d\n",va_arg(vl,char*),va_arg(vl,int)); //根据标志选择要处理的函数 switch(flag) { case _NAME: showName(va_arg(vl,char*)); break; case _NAME_AGE: name = va_arg(vl,char*); age = va_arg(vl,int); showNameAndAge(name,age); break; default: printf("没有匹配的函数!\n"); } //关闭参数列表 va_end(vl); } void showName(char* name) { printf("name=%s\n",name); } void showNameAndAge(char* name, int age) { printf("name=%s\nage=%d\n",name,age); }
(我用的是vim编辑的,可能界面有些人会不习惯。上张我的vim编辑图)
感兴趣的朋友,我可以把我的vimrc共享,目前文件配置超过600行,分割了一下感觉好点了。
vim初用很难受,用久了就月来越离不开了。程序员编程利器,建议学一下。
通过这个例子的测试,我知道C的强大也是毋庸置疑的。面向过程的语言也可以借用面向对象的思想,二者没有绝对的鸿沟。对于C来说,某个方面可能不擅长,但是并不但表做不了。还有许多好玩儿的特性,待我慢慢去挖出来。
这个例子中的思想在c的很多函数都有所体现,除了文章开头介绍的open函数外还有很多。说明了在C的标准实现里面这些特性占据着很重要的的地位。借用面向对象的思想解决问题,这也便是面向过程和面向对象的结合。
最近要写点对面向对象的思考。是时候总结一下了。
http://www.cnblogs.com/chinazhangjie/archive/2012/08/18/2645475.html
http://club.topsage.com/thread-2263309-1-1.html有关