如何用C来模拟实现多态?
要实现多态,首先咱们应充分了解多态的原理。
C++是如何实现多态的?函数
在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。若是对象类型是派生类,就调用派生类的函数;若是对象类型是基类,就调用基类的函数。布局
也就是说:
若是类中包含了虚函数–>类对象大小+4个字节–>地址(虚表)–>虚函数集合(虚函数表)
基类虚表:按照基类虚函数的声明次序将其添加到基类的虚表中
派生类:
一、将基类虚表中内存拷贝一份
二、若是派生类重写基类中某个虚函数,用派生类本身的虚函数替换虚表中相同偏移量位置的基类虚函数
三、将派生类本身的虚函数添加在虚表的最后测试
多态调用原理(条件知足):
一、确认是否为虚函数–>否(call)
二、从对象的前四个字节取虚表地址–>虚函数地址
三、传参
四、调用this
咱们能够用结构体和函数指针实现,以下:.net
// 几个基本的函数,对应抽象类中的虚函数
void foo1()
{
printf("base foo1 \r\n");
}指针
void foo2(int i)
{对象
}blog
void foo3(int i, int j)
{内存
}it
// 虚表,包含了虚函数的指针
typedef struct Vtbl
{
void(*pf1)();
void(*pf2)(int);
void(*pf3)(int, int);
}Vtbl;
// 类的虚表
Vtbl g_vtbl = { &foo1, &foo2, &foo3, };
// 基类,开始处是虚表指针,后面是结构成员。
typedef struct Base
{
//Vtbl *pvtbl;
void *pvtbl;
int field1;
int field2;
}Base;
// 构造函数
// 也是一个普通的成员函数,须要一个this指针
void InitBase(Base *p)
{
p->pvtbl = &g_vtbl;
p->field1 = 0x1234;
p->field2 = 0x5678;
}
// 子类中的虚函数,重载了父类中的同类型函数
void Sfoo1()
{
// 能够考虑调用父类中的函数
// foo1();
printf("derive foo1 \r\n");
}
void Sfoo4(char *s)
{
printf("hello %s\r\n", s);
}
// 子类中的虚表,由于内存布局是同样的
// 直接使用父类的
typedef struct SVtbl
{
Vtbl vtbl;
void(*pf4)(char *);
}SVtbl;
// 子类的虚表
SVtbl g_svtbl = { { &Sfoo1, &foo2, &foo3, }, &Sfoo4, };
// 某个子类,包含父类的内容
// 还有本身的成员
typedef struct Derive
{
Base a;
int field3;
}Derive;
// 构造函数
// 也是一个普通的成员函数,须要一个this指针
void InitDerive(Derive *p)
{
InitBase((Base*)p);
p->a.pvtbl = &g_svtbl;
p->field3 = 0xabcd;
}
void TestPolymorphism(Base *p)
{
// 虽然使用的是父类型的指针
// 但虚函数最终会根据对象的真实类型调用。
(*((Vtbl*)p->pvtbl)->pf1)();
}
void TestVtbl()
{
// 子类的一个对象
Derive s;
Base *p = 0;
// 初始化
InitDerive(&s);
p = (Base*)&s;
// 调用Sfoo4
((SVtbl*)p->pvtbl)->pf4("Sfoo4");
// 测试多态
TestPolymorphism((Base*)&s);
}
int main() { TestVtbl(); system("pause"); return 0; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 结果: