如下一段C++代码,翻译成为C++代码,实现虚函数展现多态性的原理
class Base {
int data;
public:
Base() : data(3) {}
virtual int getData() const {
return data;
}
};
class Circle:public Base {
int data;
public:
Circle() : data(5) {}
int getData() const {
return data;
}
};
分析:
c++虚函数实现多态的原理是:C++编译器为每个含虚函数的类提供一个虚表(虚拟继承形成的虚类表暂不讨论),虚表用来记录虚函数的地址,即虚表中的的指针指向虚函数的地址。当子类继承父类时,子类重写父类虚函数,虚表中的虚函数地址会更新为子类中的虚函数地址,虚表指针指向子类虚函数,通过父类指针调用子类重写的虚函数时,以此实现多态。
利用结构体和函数指针,可以用C实现C++的虚函数的多态性。
上面代码用C翻译如下:
#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
typedef void (*VirtualFunPointer)(...);//虚函数指针
typedef int BOOLEAN;
/**
构造虚表的结构体
**/
struct VTable
{
//通过函数指针,实现虚函数调用
VirtualFunPointer pFunc};
/**
类base对应的c++代码
**/
struct Base
{
int data;
//多态机制时,c++插入一个虚表,里面记录虚函数被调用的入口地址,只要基类有
//虚函数,则虚表指针应该被加入
VTable *pVTable;
};
Base *Base_Constructor(Base *this_ptr,int data);//基类里面的构造函数
int Base_getData(Base *this_ptr);//基类里面的虚函数
void Base_Destructor(Base *this_ptr,BOOLEAN dynamic);//基类里面的虚拟函数
//记录基类中虚函数的入口地址
VTable VTableArrayForBase[]=
{
(VirtualFunPointer)Base_getData,
(VirtualFunPointer)Base_Destructor
};
//基类中的方法实现
int Base_getData(Base *this_ptr)
{
printf("调用的是Base_getData方法\n");
return this_ptr->data;
}
//构造函数
Base *Base_Constructor(Base *this_ptr,int data)
{
if(this_ptr==NULL)
{
this_ptr=(Base*)malloc(sizeof(Base));
}
if(this_ptr)
{
this_ptr->pVTable=VTableArrayForBase;//构造方法中进行虚表创建和虚表指针初始化
this_ptr->data=data;
}
return this_ptr;
}
//析构函数
void Base_Destructor(Base *this_ptr,BOOLEAN dynamic)
{
this_ptr->pVTable=VTableArrayForBase;
if(dynamic)
{
free(this_ptr);
}
}
//子类
struct Circle
{
int data;
VTable *pVTable;//每一个含虚函数的类都会有一个虚表
};
Circle *Circle_Constructor(Circle *this_ptr,int data);//子类构造方法
int Circle_getData(Circle *this_ptr);//重写虚函数
void Circle_Destructor(Circle *this_ptr,BOOLEAN dynamic);//析构
//虚表
VTable VTableArrayForCircle[]=
{
(VirtualFunPointer)Circle_getData,
(VirtualFunPointer)Circle_Destructor
};
Circle *Circle_Constructor(Circle *this_ptr,int data)
{
if(this_ptr==NULL)
{
this_ptr=(Circle *)malloc(sizeof(Circle));
}
if(this_ptr)
{
//继承,先调用父类构造函数
Base_Constructor((Base*)this_ptr,data);
this_ptr->pVTable=VTableArrayForCircle;//更新虚表中的虚表函数地址
}
return this_ptr;
}
void Circle_Destructor(Circle *this_ptr,BOOLEAN dynamic)
{
this_ptr->pVTable=VTableArrayForCircle;
Base_Destructor((Base *)this_ptr,FALSE);
if(dynamic)
{
free(this_ptr);
}
}
int Circle_getData(Circle *this_ptr)
{
printf("调用的是Circle_getData方法\n");
return this_ptr->data;
}
int main(int argc,char* argv[])
{
Base *pBase=(Base *)Circle_Constructor(NULL,3);//
Circle aCircle;
Circle_Constructor(&aCircle,5);
printf("pBase->data:%d\n",pBase->data);
(pBase->pVTable->pFunc)(pBase,TRUE);
int a=Circle_getData(&aCircle);
printf("a is %d\n",a);
Circle_Destructor(&aCircle,FALSE);
return 0;
}
运行结果:
pBase->data:3
调用的是Circle_getData方法