在最近工作中,每天看的代码都是C++代码,而以前很长一段时间写的都是纯C代码,考虑到本人记忆力逐年下降,现在将以前工作中C语言一些常用经验记录下来。
这篇文章主要记录C语言如何实现面向对象语言C++的多态特性。
先说C++的多态,C++中多态通常分为编译期多态和运行时多态,函数重载就是常见的编译期多态,使用virtual修饰的函数通常就表现为运行时多态了。这篇文章主要讲运行时多态,C++运行时多态的实现通常在父类与子类,父类中函数用virtual修饰,子类中必须要定义与父类函数名称、参数列表、返回值一样的函数;话不多说,看下面的代码:
//cls.h namespace cpp { template <typename T> class CBase { public: T *data; virtual void display1() { std::cout<<"display 1 CBase"<<std::endl; } virtual void display2() { std::cout<<"display 2 CBase"<<std::endl; } }; template <typename T> class CDerived1 : public CBase<T> { public: void display1() { std::cout<<"CDerived1 display 1 "<<std::endl; } void display2() { std::cout<<"CDerived1 display 2 "<<std::endl; } }; template <typename T> class CDerived2 : public CBase<T> { public: void display1() { std::cout<<"CDerived2 display 1 "<<std::endl; } void display2() { std::cout<<"CDerived2 display 2 "<<std::endl; } }; }测试程序为:
//main.cpp ... ... cpp::CBase<int> *pB = NULL; cpp::CDerived1<int> derived1; pB = dynamic_cast<cpp::CBase<int> *>(&derived1); pB->display1(); pB->display2(); cpp::CDerived2<int> derived2; pB = dynamic_cast<cpp::CBase<int> *>(&derived2); pB->display1(); pB->display2(); ... ...执行结果为:
CDerived1 display 1 CDerived1 display 2 CDerived2 display 1 CDerived2 display 2
实现C语言实现运行时多态的关键点是函数指针,而结构体(A)中一般会有函数指针;这样当我们要使用该结构体时,只要将其函数指针成员指向一个指定的函数时,后续执行就会调用该指定函数。
考虑到上面这个例子实现了2个成员函数display1()和display2()的多态,上面那段话就得改下,这里我们定义一个结构体(Func_t),结构体成员为display1()和display2()型的函数指针,然后将Func_t替换为结构体A中的函数指针;如此就实现了多个函数的多态。代码如下:
//cls.h ... ... //纯C程序命名空间 namespace virtual_c { //定义一种函数指针类型 typedef void (*fnT)(); typedef struct _DispFunc { fnT disp1; fnT disp2; }DispFunc_t, *DispFuncP_t; void one_display1() { std::cout<<"C Programing : one_display1"<<std::endl; } void one_display2() { std::cout<<"C Programing : one_display2"<<std::endl; } void two_display1() { std::cout<<"C Programing : two_display1"<<std::endl; } void two_display2() { std::cout<<"C Programing : two_display2"<<std::endl; } DispFunc_t DispFuncOne = { one_display1, one_display2 }; DispFunc_t DispFuncTwo = { two_display1, two_display2 }; typedef struct _Base { void *data; DispFuncP_t functions; }Base_t, *BaseP_t; typedef enum en_func_type { ONE, TWO }; void SetFuncByType(BaseP_t pBase, en_func_type type) { switch (type) { case ONE: pBase->functions = &DispFuncOne; break; case TWO: pBase->functions = &DispFuncTwo; break; default: printf("非法的类型\n"); break; } } } ... ...上面的 void SetFuncByType(BaseP_t pBase, en_func_type type)函数是根据指定的type类型设置相应的执行函数。
测试程序:
// main.cpp ... ... /* * C 语言实现多态,为方便比较,这里可以设置两种枚举类型ONE/TWO * ONE对应上面的CDerived1类,TWO对应上面的CDerived2类 */ virtual_c::BaseP_t pBase = (virtual_c::BaseP_t)malloc(sizeof(virtual_c::Base_t)); virtual_c::DispFuncP_t pFunc = NULL; virtual_c::SetFuncByType(pBase, virtual_c::ONE); pFunc = pBase->functions; pFunc->disp1(); pFunc->disp2(); virtual_c::SetFuncByType(pBase, virtual_c::TWO); pFunc = pBase->functions; pFunc->disp1(); pFunc->disp2(); free(pBase); ... ...执行结果为:
C Programing : one_display1 C Programing : one_display2 C Programing : two_display1 C Programing : two_display2
原文:http://blog.csdn.net/lming_08/article/details/21543039