本文内容来自于对狄泰学院 唐佐林老师 C++深度解析 课程的学习总结
继承对象模型
在 C++ 编译器的内部 类可以理解为结构体
子类是由 父类成员叠加子类新成员 得到的
下面我们来编写一段程序来验证
#include <iostream>
using namespace std;
class Parent
{
protected:
int m_i;
int m_j;
};
class Child : public Parent
{
public:
int m_k;
};
int main()
{
cout << "sizeof(Parent) = " << sizeof(Parent) << endl;
cout << "sizeof(Child) = " << sizeof(Child) << endl;
return 0;
}
运行结果
实验结果:子类继承了父类成员变量的内存空间
C++ 多态的实现原理
当类中 声明虚函数 时,编译器会在类中 生成一个虚函数表
虚函数表是一个 存储成员函数地址的数据结构
虚函数表是 由编译器自动生成与维护的
virtual 成员函数会被编译器 放入虚函数表中
存在虚函数时,每个对象都有一个指向虚函数表的指针
下面我们根据多态实现的原理,通过C语言来实现多态
通过结构体来模拟类,子类通过结构体包含来模拟继承关系,最终通过函数指针来实现多态
Demo.h
#ifndef _DEMO_H_
#define _DEMO_H_
typedef void Demo;
Demo *Demo_Creat(int i, int j);
int Demo_GetI(Demo *pthis);
int Demo_GetJ(Demo *pthis);
void Demo_Free(Demo *pthis);
int Demo_Add(Demo *pthis, int val);
typedef void Derived;
Derived *Derived_Creat(int i, int j, int k);
int Derived_GetI(Demo *pthis);
int Derived_GetJ(Demo *pthis);
int Derived_GetK(Demo *pthis);
int Derived_add(Derived *pthis, int val);
#endif
Demo.c
#include <stdio.h>
#include <malloc.h>
#include "Demo.h"
struct DemoClass
{
struct VTable *pVtl;
int m_i;
int m_j;
};
struct DerivedClass
{
struct DemoClass d;
int m_k;
};
/* 虚拟列表*/
struct VTable
{
int (*pAdd)(void *, int);
};
static int Demo_Virtual_Add(Demo *pthis, int val);
static int Derived_Virtual_Add(Derived *pthis, int val);
/*父类虚函数列表 */
static struct VTable g_DemoVtal = {
Demo_Virtual_Add
};
/* 子类虚拟函数列表 */
static struct VTable g_Virtual_Derived = {
Derived_Virtual_Add
};
Demo* Demo_Creat(int i, int j)
{
struct DemoClass *pthis = (struct DemoClass *)malloc(sizeof(struct DemoClass));
if(pthis == NULL)
return NULL;
pthis->pVtl = &g_DemoVtal;
pthis->m_i = i;
pthis->m_j = j;
return pthis;
}
int Demo_GetI(Demo *pthis)
{
struct DemoClass *demo = (struct DemoClass *)pthis;
return demo->m_i;
}
int Demo_GetJ(Demo *pthis)
{
struct DemoClass *demo = (struct DemoClass *)pthis;
return demo->m_j;
}
static int Demo_Virtual_Add(Demo *pthis, int val)
{
struct DemoClass *demo = (struct DemoClass *)pthis;
return (demo->m_i + demo->m_j + val);
}
int Demo_Add(Demo *pthis, int val)
{
struct DemoClass *demo = (struct DemoClass *)pthis;
return demo->pVtl->pAdd(pthis, val);
}
void Demo_Free(Demo *pthis)
{
free(pthis);
}
Derived *Derived_Creat(int i, int j, int k)
{
struct DerivedClass *Derv = (struct DerivedClass *)malloc(sizeof(struct DerivedClass));
Derv->d.pVtl = &g_Virtual_Derived;
Derv->d.m_i = i;
Derv->d.m_j = j;
Derv->m_k = k;
return Derv;
}
int Derived_GetI(Demo *pthis)
{
struct DerivedClass *Derv = (struct DerivedClass *)pthis;
return Derv->d.m_i;
}
int Derived_GetJ(Demo *pthis)
{
struct DerivedClass *Derv = (struct DerivedClass *)pthis;
return Derv->d.m_j;
}
int Derived_GetK(Demo *pthis)
{
struct DerivedClass *Derv = (struct DerivedClass *)pthis;
return Derv->m_k;
}
static int Derived_Virtual_Add(Derived *pthis, int val)
{
struct DerivedClass *Derv = (struct DerivedClass *)pthis;
return (Derv->d.m_i + Derv->d.m_j + Derv->m_k + val);
}
int Derived_add(Derived *pthis, int val)
{
struct DerivedClass *Derv = (struct DerivedClass *)pthis;
return Derv->d.pVtl->pAdd(pthis, val);
}
main.c
#include <stdio.h>
#include "Demo.h"
void run(Demo *pthis, int val)
{
int ret = Demo_Add(pthis, val);
printf("run: ret = %d\n", ret);
}
int main(void)
{
Demo *classdemo = Demo_Creat(1, 2);
int i = Demo_GetI(classdemo);
int j = Demo_GetJ(classdemo);
printf("i = %d\n", i);
printf("j = %d\n", j);
Derived *classderived = Derived_Creat(10, 20, 30);
int ret = Demo_Add(classdemo, 3);
printf("Demo_Add: ret = %d\n", ret);
ret = Derived_add(classderived, 40);
printf("Derived_add: ret = %d\n", ret);
run(classdemo, 3);
run(classderived, 40);
Demo_Free(classderived);
Demo_Free(classdemo);
return 0;
}
运行结果:
实验结果:run 函数实现了多态特性,通过父类子类对象指针的传入,实现了对应的对象功能
小结
继承的本质就是 父子间成员变量的叠加
C++ 中的多态是 通过虚函数表实现的
虚函数表是 由编译器自动生成与维护的
虚函数的调用效率 低于 普通成员函数