乐清市住房和城乡建设规划局网站,网站建设维护宣传,如何做原创漫画网站,太原做网络推广的公司加qq1126137994#xff0c;微信#xff1a;liu1126137994 一起学习更多技术#xff01;#xff01;#xff01;
今天来继续学习C对象模型#xff01;
在C编译器内部#xff0c;类可以理解为结构体子类是由父类成员叠加子类新成员得到的
下面来写一个程序分析C的继承…加qq1126137994微信liu1126137994 一起学习更多技术
今天来继续学习C对象模型
在C编译器内部类可以理解为结构体子类是由父类成员叠加子类新成员得到的
下面来写一个程序分析C的继承类的模型
#include iostream
#include stringusing namespace std;class Demo
{
protected:int mi;int mj;
public:virtual void print(){cout mi mi , mj mj endl;}
};class Derived : public Demo
{int mk;
public:Derived(int i, int j, int k){mi i;mj j;mk k;}void print(){cout mi mi , mj mj , mk mk endl;}
};struct Test
{//void* p; //模拟C中的指向虚函数表的指针int mi;int mj;int mk;
};int main()
{cout sizeof(Demo) sizeof(Demo) endl; // 加上虚函数virtual后大小变为12//因为编译器发现是虚函数的时候会自动//生成一个指针指向虚函数表cout sizeof(Derived) sizeof(Derived) endl; Derived d(1, 2, 3);Test* p reinterpret_castTest*(d); //p与d类型不同需要用reinterpret_cast进行类型转换cout Before changing ... endl;d.print();p-mi 10; //p作为外界的结构体竟然可以访问d的变量说明p的内存结构与d的相同p-mj 20;p-mk 30;cout After changing ... endl;d.print();return 0;
}注意以上程序用编译器是gcc编译器所以结构体的字节对齐是4字节默认
运行结果为
那么久引出了问题C多态的实现原理是什么
C多态的实现原理
当类中声明一个虚函数时编译器会在类中生成一个虚函数表虚函数表是一个存储成员函数地址的数据结构虚函数表是由编译器自动生成与维护的virtual成员函数会被编译器放进虚函数表中存在虚函数时每个对象中都有一个指向虚函数表的指针
如下图 virtual成员函数会被编译器放进虚函数表中
存在虚函数时每个对象中都有一个指向虚函数表的指针
我们会发现虚函数的调用过程比普通函数的调用过程复杂所以虚函数的执行效率低于普通成员函数
下面给出用C语言实现的C中的虚函数表的相关概念 51-2.h为
#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
51-2.c为
#include 51-2.h
#include malloc.hstatic 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 //static关键字将该虚函数表隐藏在当前文件内外部不可见//类似于C中虚函数表是自动生成的外部不可见。
{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);
}
main.c为
#include stdio.h
#include 51-2.hvoid 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中的多态是通过虚函数表实现的虚函数表是由编译器自动生成与维护的虚函数的调用效率低于普通成员函数的调用效率
想获得各种学习资源以及交流学习的加我 qq1126137994 微信liu1126137994 可以共同交流关于嵌入式Linux操作系统C语言C语言数据结构与算法等技术问题。