第51课 继承对象模型分析——多态的本质分析

多态的本质分析

用C写面向对象,用C实现多态

#ifndef _51_2_H_
#define _51_2_H_

typedef void Demo;
typedef void Derived;

Demo* Demo_Create(int i, int j);
int Demo_GetI(Demo* pThis);
int Demo_GetJ(Demo* pThis);
int Demo_Add(Demo* pThis, int value);
void Demo_Free(Demo* pThis);

Derived* Derived_Create(int i, int j, int k);
int Derived_GetK(Derived* pThis);
int Derived_Add(Derived* pThis, int value);

#endif
#include "51-2.h"
#include "malloc.h"

static int Demo_Virtual_Add(Demo* pThis, int value);
static int Derived_Virtual_Add(Demo* pThis, int value);

struct VTable     // 2. 定义虚函数表数据结构
{
    int (*pAdd)(void*, int);   // 3. 虚函数表里面存储什么???
};

struct ClassDemo
{
    struct VTable* vptr;     // 1. 定义虚函数表指针  ==》 虚函数表指针类型???
    int mi;
    int mj;
};

struct ClassDerived
{
    struct ClassDemo d;
    int mk;
};

static struct VTable g_Demo_vtbl =
{
    Demo_Virtual_Add
};

static struct VTable g_Derived_vtbl =
{
    Derived_Virtual_Add
};

Demo* Demo_Create(int i, int j)
{
    struct ClassDemo* ret = (struct ClassDemo*)malloc(sizeof(struct ClassDemo)); 

    if( ret != NULL )
    {
        ret->vptr = &g_Demo_vtbl;   // 4. 关联对象和虚函数表
        ret->mi = i;
        ret->mj = j;
    }

    return ret;
}

int Demo_GetI(Demo* pThis)
{
     struct ClassDemo* obj = (struct ClassDemo*)pThis;    

     return obj->mi;
}

int Demo_GetJ(Demo* pThis)
{
    struct ClassDemo* obj = (struct ClassDemo*)pThis;

    return obj->mj;
}

// 6. 定义虚函数表中指针所指向的具体函数
static int Demo_Virtual_Add(Demo* pThis, int value)
{
    struct ClassDemo* obj = (struct ClassDemo*)pThis;

    return obj->mi + obj->mj + value;
}

// 5. 分析具体的虚函数!!!!
int Demo_Add(Demo* pThis, int value)
{

    struct ClassDemo* obj = (struct ClassDemo*)pThis;

    return obj->vptr->pAdd(pThis, value);
}

void Demo_Free(Demo* pThis)
{
    free(pThis);
}

Derived* Derived_Create(int i, int j, int k)
{
    struct ClassDerived* ret = (struct ClassDerived*)malloc(sizeof(struct ClassDerived));

    if( ret != NULL )
    {
        ret->d.vptr = &g_Derived_vtbl;
        ret->d.mi = i;
        ret->d.mj = j;
        ret->mk = k;
    }

    return ret;
}

int Derived_GetK(Derived* pThis)
{
    struct ClassDerived* obj = (struct ClassDerived*)pThis;

    return obj->mk;
}

static int Derived_Virtual_Add(Demo* pThis, int value)
{
    struct ClassDerived* obj = (struct ClassDerived*)pThis; 

    return obj->mk + value;
}

int Derived_Add(Derived* pThis, int value)
{
    struct ClassDerived* obj = (struct ClassDerived*)pThis;

    return obj->d.vptr->pAdd(pThis, value);
}
#include "stdio.h"
#include "51-2.h"

void run(Demo* p, int v)
{
    int r = Demo_Add(p, v);

    printf("r = %d\n", r);
}

int main()
{
    Demo* pb = Demo_Create(1, 2);
    Derived* pd = Derived_Create(1, 22, 333);

    printf("pb->add(3) = %d\n", Demo_Add(pb, 3));
    printf("pd->add(3) = %d\n", Derived_Add(pd, 3));

    run(pb, 3);
    run(pd, 3);

    Demo_Free(pb);
    Demo_Free(pd);

    return 0;
}

继承的本质就是父子间成员变量的叠加
C++中的多态是通过虚函数表实现的
虚函数表是由编译器自动生成与维护的
虚函数的调用效率低于普通成员函数

原文地址:https://www.cnblogs.com/-glb/p/11967244.html

时间: 2024-10-07 13:29:22

第51课 继承对象模型分析——多态的本质分析的相关文章

第51课 C++对象模型分析(下)

1. 单继承对象模型 (1)单一继承 [编程实验]继承对象模型初探 #include <iostream> using namespace std; class Demo { protected: int mi; int mj; public: //虚函数 virtual void print() { cout << "mi = " << mi << ", " << "mj = " &l

C++--第17课 - 继承与多态 - 上

第17课 - 继承与多态 - 上 引入: 如果子类定义了与父类中原型相同的函数会发生什么? 1. 函数重写 在子类中定义与父类中原型相同的函数,函数重写只发生在父类与子类之间. 父类中被重写的函数依然会继承给子类,默认情况下子类中重写的函数将隐藏父类中的函数,通过作用域分辨符::可以访问到父类中被隐藏的函数. #include <cstdlib> #include <iostream> using namespace std; class Parent { public: void

第50课 C++对象模型分析(上)

1. 回归本质 (1)class是一种特殊的结构体 ①在内存中class依旧可以看作变量的集合 ②class与struct遵循相同的内存对齐规则 ③class中的成员函数与成员变量是分开存放的.即每个对象有独立的成员变量,但所有对象共享类中的成员函数. [编程实验]对象内存布局初探 #include <iostream> #include <string> using namespace std; class A { //默认访问权限为private int i; int j; c

C++--第16课 - 继承中的构造与析构

第16课 - 继承中的构造与析构 1. 赋值兼容性原则 (1)      子类对象可以当作父类对象使用. (2)      子类对象可以直接赋值给父类对象. (3)      子类对象可以直接初始化父类对象. (4)      父类指针可以直接指向子类对象. (5)      父类引用可以直接引用子类对象. 子类就是特殊的父类 #include <cstdlib> #include <iostream> using namespace std; class Parent { pro

【Cocos游戏实战】功夫小子第六课之游戏主功能场景的分析和实现

本节课的视频教程地址是:第六课在此 如果本教程有帮助到您,希望您能点击进去观看一下,而且现在注册成为极客学院的会员,验证手机号码和邮箱号码会赠送三天的会员时间,手机端首次也可以领取五天的会员时间哦(即使是购买年会员目前也仅仅是年费260),成为极客学院学习会员可以无限制的下载和观看所有的学院网站的视频,谢谢您的支持! 转载请注明出处:http://blog.csdn.net/suool/article/details/46851335 前言 经过前面五节课的学习我们目前还剩的未完成的工作就是游戏

面向对象--多继承&amp;派生类对象内存布局分析&amp;各基类指针所指向的位置分析

背景 原文链接:ordeder  http://blog.csdn.net/ordeder/article/details/25477363 关于非虚函数的成员函数的调用机制,可以参考: http://blog.csdn.net/yuanyirui/article/details/4594805 成员函数的调用涉及到面向对象语言的反射机制. 虚函数表机制可以查看下面这个blog: http://blog.csdn.net/haoel/article/details/1948051 总结为: 其一

探索单继承对象模型

探索单继承对象模型 class Base { public : virtual void func1() { cout<<"Base::func1" <<endl; } virtual void func2() { cout<<"Base::func2" <<endl; } private : int a ; }; class Derive :public Base { public : virtual void fu

【51课代表推荐系列】Excel专场优惠篇,购课满99元即送超值礼包!

无论身在职场还是未出校园,处理数据怎么都离不开办公软件.如何告别繁琐的操作,把工作效率提升10倍?今天51课代表要为大家推荐最值得掌握的办公技能--Excel! 此次专场福利:凡购买以下课程满499元,赠送价值89元的51CTO学院主题T恤一件满299元,赠送价值50元的日式抱枕一个满99元,回馈学院1000学分 Excel技巧篇 推荐语:在Excel的使用过程中,很多人没有掌握软件提供的功能,经常费了九牛二虎之力才得到想要的结果,其实Excel本身有很多的技巧,只要掌握就能够事半功倍! 推荐课

算法课笔记系列(七)—— 平摊分析

本周的内容是Amortized Analysis,是对算法复杂度的另一种分析.它的基本概念是,给定一连串操作,大部分的操作是非常廉价的,有极少的操作可能非常昂贵,因此一个标准的最坏分析可能过于消极了.因此,其基本理念在于,当昂贵的操作也别少的时候,他们的成本可能会均摊到所有的操作上.如果人工均摊的花销仍然便宜的话,对于整个序列的操作我们将有一个更加严格的约束.本质上,均摊分析就是在最坏的场景下,对于一连串操作给出一个更加严格约束的一种策略. 均摊分析与平均情况分析的区别在于,平均情况分析是平均所