c++中的多态和多态对象模型
来源:互联网 发布:华夏免费版数据库 编辑:程序博客网 时间:2024/06/08 18:48
1.什么是多态?
多态顾名思义,就是“多种形态”
在c++中,我们是通过虚函数来实现多态的
那么什么是虚函数呢?
虚函数就是在类的成员函数的前面加上virtual关键字,那么该成员函数就是虚函数
在c++中多态形成的条件是什么呢?
1.虚函数的重写;
2.父类的指针或引用调用重写的虚函数。
class A{public: virtual void f1(){cout<<"A::f1()"<<endl;}};class B : public A{public:virtual void f1(){cout<<"B::f1()"<<endl;}};void Test(){B b;//b是一个子类对象A *p = &b;//此时形成了多态,这个时候调用函数与类型无关,只与指向对象有关,指向谁就调用谁}在这里我们进行了虚函数的重写,什么是虚函数的重写呢?
当子类定义了一个和父类完全相同的虚函数(返回值、函数名、可变参数列表)时,则称为重写。
特例:协变 A类虚函数的返回值可定义为A类的指针或引用 B类也是可以定义为B类的。(可以看做是切片类型)
//特例class A{public:A* fun(){}};class B : public A{public:B* fun(){}//此时也构成了重写};
1. 单继承:一个类只有一个直接父类时称这个继承关系为单继承
2. 多继承:一个类有两个或以上直接父类时称这个继承关系为多继承
在这里需要了解一下虚表
虚表就是存了虚函数的表
虚函数能够实现多态的重要原因是有一个虚表指针指向了虚函数表,这样就可以通过指针来找到xuhans
单继承
//打印虚表typedef void(*V_FUNC)(); //定义一个函数指针void PrintVtable(int* vtable){printf("vtable 0x%p\n",vtable);int** ppvtable = (int**)vtable;for(size_t i=0; ppvtable[i]!=0; i++){printf("vatable[%u]::0x%p->",i,ppvtable[i]);V_FUNC f = (V_FUNC)ppvtable[i];f();}}//单继承class Base{public:virtual void fun1(){cout<<"Base::fun1()"<<endl;}virtual void fun2(){cout<<"Base::fun2()"<<endl;}private:int _a;};class Derive : public Base{public:virtual void fun1(){cout<<"Derive::fun1()"<<endl;}virtual void fun3(){cout<<"Derive::fun1()"<<endl;}};int main(){Base b;Derive d;PrintVtable(*((int**)&b));PrintVtable(*((int**)&d));return 0;}通过调试监视窗口,我们可以发现单继承的对象模型
多继承
//打印虚表typedef void(*V_FUNC)(); //定义一个函数指针void PrintVtable(int* vtable){printf("vtable 0x%p\n",vtable);int** ppvtable = (int**)vtable;for(size_t i=0; ppvtable[i]!=0; i++){printf("vatable[%u]::0x%p->",i,ppvtable[i]);V_FUNC f = (V_FUNC)ppvtable[i];f();}}//多继承class Base1{public:void virtual Fun1(){cout<<"Base1::Fun1()"<<endl;}void virtual Fun2(){cout<<"Base1::Fun2()"<<endl;}private:int _b;};class Base2{public:void virtual Fun1(){cout<<"Base2::Fun1()"<<endl;}void virtual Fun3(){cout<<"Base2::Fun3()"<<endl;}private:int _b;};class Derive:public Base1,public Base2{public:void virtual Fun1(){cout<<"Derive::Fun1()"<<endl;//覆盖}void virtual Fun3(){cout<<"Derive::Fun3()"<<endl;}private:int _d;};int main(){Base1 b1;Base2 b2;Derive d;PrintVtable(*((int**)&b1));PrintVtable(*((int**)&b2));PrintVtable(*((int**)&d));PrintVtable(*((int**)((char*)&d+sizeof(Base1))));return 0;}
3.菱形虚拟继承
//打印虚表typedef void(*V_FUNC)(); //定义一个函数指针void PrintVtable(int* vtable){printf("vtable 0x%p\n",vtable);int** ppvtable = (int**)vtable;for(size_t i=0; ppvtable[i]!=0; i++){printf("vatable[%u]::0x%p->",i,ppvtable[i]);V_FUNC f = (V_FUNC)ppvtable[i];f();}}//菱形继承class Base{public:void virtual Fun1(){cout<<"Base::Fun1()"<<endl;}void virtual Fun2(){cout<<"Base::Fun2()"<<endl;}public:int _b;};class Derive1:virtual public Base{public:void virtual Fun1(){cout<<"Derive1::Fun1()"<<endl;}void virtual Fun3(){cout<<"Derive1::Fun3()"<<endl;}public:int _d1;};class Derive2:virtual public Base{public:void virtual Fun1(){cout<<"Derive2::Fun1()"<<endl;}void virtual Fun4(){cout<<"Derive2::Fun4()"<<endl;}public:int _d2;};class Derive:public Derive1,public Derive2{public:void virtual Fun1(){cout<<"Derive::Fun1()"<<endl;//覆盖}void virtual Fun5(){cout<<"Derive::Fun5()"<<endl;}public:int _d;};int main(){Derive d;d._b = 2;d._d1 = 3;d._d2 = 4;d._d = 5;PrintVtable(*((int**)&d));return 0;}
菱形虚拟继承的对象模型
在我们的菱形虚拟继承中,又有虚表也有虚基表,那么就需要我们在编译代码中看看内存中的状况,在图中我们可以看到,我们把基类的对象存为共有的,因此需要用虚基表用偏移量找到他。这里注意虚函数的重写,因为看的是Derive的对象模型,所以在继承的时候,有的函数进行了重写。
阅读全文
0 0
- C++中的多态和多态对象模型
- c++中的多态和多态对象模型
- 【C++】多态及其对象模型
- 【c++】多态&多态对象模型
- 多态和多态对象模型
- C++对象模型和多态
- 多态对象模型
- python中的多态和鸭子模型
- C++_多态&多态的对象模型
- 多态中的模型
- 多态&多态对象模型
- 多态&多态对象模型
- 多态及其对象模型
- 多态&多态对象模型
- 多态的对象模型
- 多态&多态对象模型
- 多态&多态对象模型
- 多态&多态对象模型
- MyEclipse安装其他插件比如maven后svn不起作用
- SDUT-山峰
- kubernetes资源对象--secret和Service Account
- 学密码学一定得学程序(串)
- mysql免安装配置
- c++中的多态和多态对象模型
- javax.xml.transform.TransformerFactoryConfigurationError异常处理
- vue组件的一个总结
- 根据标签框出人和关键点
- ActiveRecord插件Db +Record 模式常用方法
- 文件操作——将数据导出到Excel
- jquery如何判断滚动条滚到页面底部并执行事件
- C语言实现图的最短路径Floyd算法
- matlab中几种取整函数的用法(fix, floor, ceil, round)