用C来模拟实现多态?

如何用C来模拟实现多态?

要实现多态,首先我们应充分了解多态的原理。
C++是如何实现多态的?

在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数。

也就是说:
如果类中包含了虚函数–>类对象大小+4个字节–>地址(虚表)–>虚函数集合(虚函数表)
基类虚表:按照基类虚函数的声明次序将其添加到基类的虚表中
派生类:
1、将基类虚表中内存拷贝一份
2、如果派生类重写基类中某个虚函数,用派生类自己的虚函数替换虚表中相同偏移量位置的基类虚函数
3、将派生类自己的虚函数添加在虚表的最后

多态调用原理(条件满足):
1、确认是否为虚函数–>否(call)
2、从对象的前四个字节取虚表地址–>虚函数地址
3、传参
4、调用

我们可以用结构体和函数指针实现,如下:

// 几个基本的函数,对应抽象类中的虚函数
void foo1()
{
    printf("base foo1 \r\n");
}

void foo2(int i)
{

}

void foo3(int i, int j)
{

}

// 虚表,包含了虚函数的指针
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;
}

结果:
这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值