您现在的位置是:主页 > news > 龙华附近网站建设公司/百度关键词查询网站
龙华附近网站建设公司/百度关键词查询网站
admin2025/5/8 2:54:52【news】
简介龙华附近网站建设公司,百度关键词查询网站,为网站做seo需要什么软件,北京宣传片C中的继承体系,有单继承、多继承、菱形继承、菱形虚拟继承,以及各类型的对象模型,我们今天做一个简单的剖析 (1)什么多态? 所谓多态,就是“多种形态”。在面向对象的方法中一般是这样描述多态的…
龙华附近网站建设公司,百度关键词查询网站,为网站做seo需要什么软件,北京宣传片C中的继承体系,有单继承、多继承、菱形继承、菱形虚拟继承,以及各类型的对象模型,我们今天做一个简单的剖析
(1)什么多态? 所谓多态,就是“多种形态”。在面向对象的方法中一般是这样描述多态的…
多态=动态多态+静态多态
a.关于静态多态:函数重载
b.关于动态多态:
构成动态多态的两个必要条件:
(1)子类对父类的虚函数重写
(2)函数通过父类得到指针或引用进行传参
(1)探索单继承对象模型
当子类与父类构成多态时,子类继承父类的虚表之后,子类虚表里虚函数在内存里的存储情况;具体以下面例子作为分析参考:
由上图可得,一个类里面只要有虚函数,类的对象就会有虚表,例中第一个虚表中分别是
Base类中虚函数fun1,fun2的地址,第二个虚表是Drive类继承父类的虚表,明显这个虚表的内容
发生了变化,分别是Drive类中重写父类的虚函数fun1,继承父类的虚函数fun2,以及子类本身的虚函数
fun3,fun4,需要注意的是,每个虚表都以0结束
(2)探索多继承对象模型
当一个子类继承多个父类时构成多继承,此时子类会继承这些父类的虚表,子类虚表里虚函数在内存里的存储情况
具体以下面例子(2个父类)作为分析参考:
由以上例子可得,子类Drive分别继承了父类Base1,Base2,从而子类得到了两个虚表,继承Base1的
虚表中,存放了自己重写之后的虚函数fun1,继承Base1中的fun2,以及自己的fun3;
继承Base2的虚表中,存放了自己重写之后的虚函数fun1,以及继承Base2中的fun2
注意的是,这里子类自己的fun3只放在了第一个虚表中。
3:多态的对象模型--菱形继承和菱形虚拟继承?
(1)菱形继承
顾名思义,菱形继承就是,几个类的继承关系呈菱形状。
为此,我们举例解释:
例如,有A类,B类,C类,D类;其中,B类,C类继承了A类,D类继承了B类,C类。继承关系如下:
代码如下:
总结:在普通的菱形继承中,处于最先的D类型的对象d,它继承了B,C,并且B,C中分别保存了
一份来自继承A的变量;除此之外,B,C还存了虚表指针,通过它可以找到虚表中存的虚函数地址,
最后,d对象还存放了自己定义的变量和继承B,C自己定义的变量。
(2)菱形虚拟继承
菱形虚拟继承就是在普通菱形继承的前提下加了虚继承(本例是,B,C虚继承A)
创建一个D类的对象d,下图为查看d对象中存储的成员变量情况,以及虚表指向:
总结:菱形虚拟继承与菱形继承的区别在于,B,C继承A的公共成员a,既不存储在
B里,也不存储在C里,而是存储在一块公共的部分,而会将B,C相对于这个变量的
偏移地址(这里的偏移量地址叫做虚基表)存在B,C里。所以说,对象d里的B,C里存放了虚表指针,虚基表指针,
自己的变量。
C++中的继承体系,有单继承、多继承、菱形继承、菱形虚拟继承,以及各类型的对象模型,我们今天做一个简单的剖析
(1)什么多态?
所谓多态,就是“多种形态”。在面向对象的方法中一般是这样描述多态的:向不同的对象发送同一个消息,不同的对象在接收时会产生不同的行为(即方法)。多态=动态多态+静态多态
a.关于静态多态:函数重载
b.关于动态多态:
构成动态多态的两个必要条件:
(1)子类对父类的虚函数重写
(2)函数通过父类得到指针或引用进行传参
实现多态的主要技术是虚继承,当满足以上条件时,父类对象调用被重写过得虚函数,那就去父类中寻找;当子类对象调用时,就去子类中寻找重写过后的虚函数,依次来实现多态,即不同的形态。如下图:
(1)探索单继承对象模型
当子类与父类构成多态时,子类继承父类的虚表之后,子类虚表里虚函数在内存里的存储情况;具体以下面例子作为分析参考:
由上图可得,一个类里面只要有虚函数,类的对象就会有虚表,例中第一个虚表中分别是
Base类中虚函数fun1,fun2的地址,第二个虚表是Drive类继承父类的虚表,明显这个虚表的内容
发生了变化,分别是Drive类中重写父类的虚函数fun1,继承父类的虚函数fun2,以及子类本身的虚函数
fun3,fun4,需要注意的是,每个虚表都以0结束
(2)探索多继承对象模型
当一个子类继承多个父类时构成多继承,此时子类会继承这些父类的虚表,子类虚表里虚函数在内存里的存储情况
具体以下面例子(2个父类)作为分析参考:
由以上例子可得,子类Drive分别继承了父类Base1,Base2,从而子类得到了两个虚表,继承Base1的
虚表中,存放了自己重写之后的虚函数fun1,继承Base1中的fun2,以及自己的fun3;
继承Base2的虚表中,存放了自己重写之后的虚函数fun1,以及继承Base2中的fun2
注意的是,这里子类自己的fun3只放在了第一个虚表中。
3:多态的对象模型--菱形继承和菱形虚拟继承?
(1)菱形继承
顾名思义,菱形继承就是,几个类的继承关系呈菱形状。
为此,我们举例解释:
例如,有A类,B类,C类,D类;其中,B类,C类继承了A类,D类继承了B类,C类。继承关系如下:
代码如下:
#include <iostream>
using namespace std;
class A
{
public:virtual void f1(){cout<<"A::f1()"<<endl;}virtual void f2(){cout<<"A::f2()"<<endl;}
public:int _a;
};class B:public A
{
public:virtual void f1(){cout<<"B::f1()"<<endl;}virtual void f3(){cout<<"B::f3()"<<endl;}
public:int _b;};class C:public A
{
public:virtual void f1(){cout<<"C::f1()"<<endl;}virtual void f4(){cout<<"C::f4()"<<endl;}
public:int _c;
};class D:public B,public C
{
public:virtual void f1(){cout<<"D::f1()"<<endl;}virtual void f5(){cout<<"D::f5()"<<endl;}
public:int _d;
};//打印虚函数表
typedef void(*V_FUNC)();void PrintVtable(int* vtable)
{printf("vtable:%p\n",vtable);int** pvtable=(int**)vtable;for(size_t i=0; pvtable[i]!=0;i++){printf("vtable[%u]:0x%p->",i,pvtable[i]);V_FUNC f=(V_FUNC)pvtable[i];f();}cout<<"------------------------------------\n";
}void test()
{D d;d.B::_a=5;d.C::_a=6;d._b=1;d._c=2;d._d=3;PrintVtable(*(int**)&d);PrintVtable(*(int**)((char*)&d+sizeof(B)));
}int main()
{test();return 0;
}
创建一个D类的对象d,下图为查看d对象中存储的成员变量情况,以及虚表指向:
总结:在普通的菱形继承中,处于最先的D类型的对象d,它继承了B,C,并且B,C中分别保存了
一份来自继承A的变量;除此之外,B,C还存了虚表指针,通过它可以找到虚表中存的虚函数地址,
最后,d对象还存放了自己定义的变量和继承B,C自己定义的变量。
(2)菱形虚拟继承
菱形虚拟继承就是在普通菱形继承的前提下加了虚继承(本例是,B,C虚继承A)
创建一个D类的对象d,下图为查看d对象中存储的成员变量情况,以及虚表指向:
总结:菱形虚拟继承与菱形继承的区别在于,B,C继承A的公共成员a,既不存储在
B里,也不存储在C里,而是存储在一块公共的部分,而会将B,C相对于这个变量的
偏移地址(这里的偏移量地址叫做虚基表)存在B,C里。所以说,对象d里的B,C里存放了虚表指针,虚基表指针,
自己的变量。