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

网站建设自己可以建网站吗头条权重查询

网站建设自己可以建网站吗,头条权重查询,怎么用dede建设网站,hdmi高清wifi无线传输器虚表和虚基表 虚表虚基表虚拟继承和虚函数都存在时的对象模型 虚表 我们知道,如果类中声明了的方法是用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.15wanjia.com/news/24955.html

相关文章:

  • 网站优化 流量自动外链网址
  • 成都网站建设名录最新热点新闻事件
  • 最专业网站建设开发宝鸡seo优化公司
  • 网站开发怎么销售品牌策略的7种类型
  • 大型图片库网站建设百度如何免费推广
  • 东城手机网站建设舆情分析
  • 网站内链少改怎么做北京seo做排名
  • 你第一个物流网站建设方案抖音seo排名系统
  • 生鲜b2c网站建设规划书舆情视频
  • 个人网站建设制作关键词搜索工具有哪些
  • 网站建设最新活动推广网站多少钱
  • 福州市做网站公司市场调研报告800字
  • 建网站的书籍自己建网站怎样建
  • 长沙微信网站制作信息流优化
  • 网站推广的方案设计怎么写seo外包服务公司
  • 学做美食网站北京百度公司总部电话
  • 横沥网站仿做公司怎么建立自己的网站
  • 济南全网营销型网站建设河南seo关键词排名优化
  • 广东快速做网站公司宁波seo推广外包公司
  • 微网站建设方案百度网盘搜索引擎盘多多
  • 网站制作流程分为哪七步网络文章发布平台
  • 赣州培训学做网站国内新闻最新消息十条
  • 餐饮公司做网站好处查域名备案
  • 网站做facebook推广德州seo优化
  • 学校网站建设实训做微商怎么找客源加人
  • 网站图片用什么做的baidu优化
  • 做网站的业务分析建站流程新手搭建网站第一步
  • 几何背景生成器网站网站服务器搭建
  • 英文企业网站源码黄页88网
  • 自己下载的字体怎么导入wordpress南宁网站seo外包