当前位置: 首页 > news >正文

网站建设自己可以建网站吗软文是啥意思

网站建设自己可以建网站吗,软文是啥意思,中国建设银行怎么查询余额,河南手机网站建设价格明细表虚表和虚基表 虚表虚基表虚拟继承和虚函数都存在时的对象模型 虚表 我们知道,如果类中声明了的方法是用virtual进行修饰的,则说明当前这个方法要作为虚函数,而虚函数的存储和普通函数的存储是有区别的 当有虚函数声明时,编译器会…

虚表和虚基表

  • 虚表
  • 虚基表
  • 虚拟继承和虚函数都存在时的对象模型

虚表

我们知道,如果类中声明了的方法是用virtual进行修饰的,则说明当前这个方法要作为虚函数,而虚函数的存储和普通函数的存储是有区别的
当有虚函数声明时,编译器会创建一个虚函数表,将当前的虚函数按照声明次序放入虚函数表中,而这个虚函数表实际上就是一个函数指针数组,然后将当前这个虚函数表的地址放入对象模型的最起始位置。

class A
{
public:virtual void fun1(){cout << "A::fun1()" << endl;}virtual void fun2(){cout << "A::fun2()" << endl;}virtual void fun3(){cout << "A::fun3()" << endl;}int _a;
};

它对应的对象模型是这样的:
在这里插入图片描述

所以说,本质上虚函数表是一个函数指针数组,而对象模型中存放的是虚函数表的首地址,当我们需要调用虚函数时,传递对应的对象,就可以通过对象的地址获取对象的虚表指针,从而获取虚表,进而得到对应虚函数表中某个虚函数的地址,以此来进行调用(知道函数的入口地址,就可以调用对应的函数)

虚基表

我们知道,当出现菱形继承时,一定会出现对象模型中有多个基类对象成员。

//普通继承
class A
{
public:int _a;
};
class B : public A
{
public:int _b;
};
class C : public A
{
public:int _c;
};
class D : public B, public C
{
public:int _d;
};

上述代码中,D类对象中一定会存在B类和C类对象继承自A类对象的_a这个成员,这样就出现了两份_a成员,导致访问_a时出现二义性,并且随着继承深度和广度的增加,对象成员会越来越冗余。
为了解决这个问题,出现了虚拟继承。

//菱形虚拟继承
class A
{
public:int _a;
};
class B : virtual public A
{
public:int _b;
};
class C : virtual public A
{
public:int _c;
};
class D : public B, public C
{
public:int _d;
};

通过让B类和C类虚拟继承A类后,对象模型就从图1变成了图2
在这里插入图片描述

在这里插入图片描述

这样的转变,使得B类和C类虽然继承了A类,但是B类和C类中并没有存储A类的对象(基类对象只有一份,被存放在了整个对象模型的最后),除了子类新增之外,只有一个指针,这个指针就被称为虚基表指针。

虚基表指针所指向的是一个虚基表,对于B类ptr1这个虚基表,总大小为8个字节(32位系统下),前4个字节存储的是子类对象相对于自己起始位置的偏移量,(目前来看是0,当存在虚函数的虚拟继承时,就不是0了),后4个字节存储是子类对象相对于基类部分的偏移量。
在这里插入图片描述
ptr2指向C类这个对象的虚基表,总大小为8个字节(32位系统下),前4个字节存储的是子类对象相对于自己起始位置的偏移量,(目前来看是0,当存在虚函数的虚拟继承时,就不是0了),后4个字节存储是子类对象相对于基类部分的偏移量。
在这里插入图片描述

可以发现,虚表在整个类对象中只存储一份,也就是说一个类的不同对象共享同一份虚表。而虚基表有多份,取决于当前类是否虚拟继承了基类,若虚拟继承了基类,就会创建一个虚基表指针,指向一个虚基表。

虚拟继承和虚函数都存在时的对象模型

那么就存在另外一个问题,当虚拟继承和虚函数同时出现在继承体系中,对象模型又是什么样子呢?

class A
{
public:virtual void fun1(){cout << "A::fun1()" << endl;}virtual void fun2(){cout << "A::fun2()" << endl;}int _a;
}
class B : virtual public A
{
public:virtual void fun1(){cout << "B::fun1()" << endl;}virtual void fun3(){cout << "B::fun3()" << endl;}int _b;
};
class C : virtual public A
{
public:virtual void fun2(){cout << "C::fun2()" << endl;}virtual void fun4(){cout << "C::fun4()" << endl;}int _c;
};
class D : public B, public C
{
public:virtual void fun1(){cout << "D::fun1()" << endl;}virtual void fun2(){cout << "D::fun2()" << endl;}virtual void fun5(){cout << "D::fun5()" << endl;}int _d;
}

上述代码中,B类和C类都继承自A类,并且对A类中的虚函数进行了重写,同时也新增了虚函数。D类继承了B和C类,对B和C类中的虚函数进行了重写,同时也新增了虚函数。

那么当前在这个继承体系下,对象模型是什么样子呢?
其实不难想到,由于B类和C类都是虚拟继承,那么A类成员只会保留一份在最下方,同时B类和C类都会保存自己的虚基表指针,而D类由于是普通继承,按照顺序,新增的虚函数被放到B类的虚表中。
在这里插入图片描述

我们通过取地址发现,对象模型确实是上述的样子,但是在D类和A类之间,放了00000000作为对象分割区分(猜测)
在这里插入图片描述

请注意:当前的验证情况是在vs2019中进行验证的。

总结:当虚基表和虚表同时存在(虚拟继承和虚函数同时存在时),对象模型从整体上来说还是和虚拟继承相同(基类对象顺序按照声明的顺序从上到下排列,对象中没有祖父类的成员,祖父类成员被放到了模型的最下方)。但是由于有虚函数的存在,B类对A类的虚函数进行重写的虚函数在A类中直接修改,B类新增的虚函数被放到B类内部的虚表中,C类对A类的虚函数进行重写的虚函数在A类中直接修改,C类新增的虚函数被放到C类内部的虚表中。D类对B类和C类进行重写的虚函数直接在对应类中进行修改,D类新增的就直接放到B类的虚表中。

通过上述的描述,可以知道对于B类,C类和A类的虚表中存放的虚函数分别为:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

而对于虚基表来说,表示的是子类对象相对于自己起始位置的偏移量,如果是B类,B类对象的起始位置已经有了一个虚表指针,那么虚基表中前四个字节要表示相对自己起始位置的偏移量就需要为-4,而后四个字节是相对于基类的偏移量是正常的计算方式。

对于B类C类的虚基表来说,其中的值为:
在这里插入图片描述
在这里插入图片描述

http://www.ds6.com.cn/news/108745.html

相关文章:

  • 网站优化 流量emlog友情链接代码
  • 刘涛做的儿童购物网站嘉兴网站建设
  • 网站开发设计合同指数函数运算法则
  • 网站建设与网站开发阐述网络推广的主要方法
  • 苏州吴江太湖新城建设局网站营销顾问
  • 游戏平台网站开发谷歌google 官网下载
  • 有啥创意可以做商务网站的西安seo公司
  • 凡科做的网站百度不到北京债务优化公司
  • 自己做企业网站大连网站开发公司
  • 微山做网站高清网站推广免费下载
  • 哪里办网站不用备案win7优化软件
  • 做网站能赚到流量费吗天机seo
  • 郑州 网站建设福州seo网站推广优化
  • 中文域名查询抖音seo供应商
  • 网站建设论文开题报告范文深圳网站seo公司
  • 专业做冻货的网站今天的头条新闻
  • 做网站如何防止被抄袭seo是一种利用搜索引擎
  • 网站开发工程师面试试题seo点击排名软件哪里好
  • 承接php网站建设58同城推广
  • 外贸网站建设 如何做域名地址查询
  • 网站建设与管理案例教程ppt郑州网络营销与网站推广
  • 长沙诚信做网站手机百度app免费下载
  • 做网站好还是网页好网店运营与管理
  • 网站开发和嵌入式开发杭州网络推广有限公司
  • 江苏 建设 招标有限公司网站哪里有免费的网站推广软件
  • 北京市昌平区住房和城乡建设委员会网站舆情监控
  • 专业网站建设推荐q479185700顶上淘宝seo优化怎么做
  • 幼儿园网站建设培训百度推广app
  • 怎样做网站xml网站推广策划案
  • 专门做网站代购的盈利路子点击进入官方网站