C语言实现C++多态

在最近工作中,每天看的代码都是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++的运行时多态,下面再继续讨论C语言实现运行时多态。

实现C语言实现运行时多态的关键点是函数指针,而结构体(A)中一般会有函数指针;这样当我们要使用该结构体时,只要将其函数指针成员指向一个指定的函数时,后续执行就会调用该指定函数。

考虑到上面这个例子实现了2个成员函数display1()和display2()的多态,上面那段话就得改下,这里我们定义一个结构体(Func_t),结构体成员为display1()和display2()型的函数指针,然后将Func_t替换为结构体A中的函数指针;如此就实现了多个函数的多态。代码如下:

//cls.h
... ...
//纯C程序命名空间
namespace pure_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类
	 */
	pure_c::BaseP_t pBase = (pure_c::BaseP_t)malloc(sizeof(pure_c::Base_t));
	pure_c::DispFuncP_t pFunc = NULL;

	pure_c::SetFuncByType(pBase, pure_c::ONE);
	pFunc = pBase->functions;
	pFunc->disp1();
	pFunc->disp2();

	pure_c::SetFuncByType(pBase, pure_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

以上代码都是根据上一份工作抽象出来的,记得是实现一个传统关系型数据库的各种类型间的转换,每个类型的转换函数的函数指针放在上面的DispFunc_t结构体里;总之,当时的代码个人感觉非常精妙。


完整代码见:http://download.csdn.net/detail/lming_08/7066873


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值