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

flask网站开发源码天津搜索引擎seo

flask网站开发源码,天津搜索引擎seo,苏州网站 建设 公司,php做的大型网站💖作者:小树苗渴望变成参天大树🎈 🎉作者宣言:认真写好每一篇博客💤 🎊作者gitee:gitee✨ 💞作者专栏:C语言,数据结构初阶,Linux,C 动态规划算法🎄 如 果 你 …

> 提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
💖作者:小树苗渴望变成参天大树🎈
🎉作者宣言:认真写好每一篇博客💤
🎊作者gitee:gitee✨
💞作者专栏:C语言,数据结构初阶,Linux,C++ 动态规划算法🎄
如 果 你 喜 欢 作 者 的 文 章 ,就 给 作 者 点 点 关 注 吧!

文章目录

  • 前言
  • 一、虚函数表
  • 二、多态的原理
  • 三、解决疑惑
  • 四、多继承中的虚函数表
  • 五、总结


前言

今天我们开始讲解多态的底层原理,相信这篇博客会让你对多态的理解会更加的透彻,话不多说我们开始进入讲解


一、虚函数表

我们在多态语法的时候一直强调要构成虚函数,我们来看看虚函数在内存是怎么存储的?

// 这里常考一道笔试题:sizeof(Base)是多少?
class Base
{
public:virtual void Func1(){cout << "Func1()" << endl;}
private:int _b = 1;
};

在这里插入图片描述
我们发现我们对象里面存放两个内容:成员变量和一个指针地址,刚好大小就是8。====

通过观察测试我们发现b对象是8bytes,除了_b成员,还多一个__vfptr放在对象的前面(注意有些平台可能会放到对象的最后面,这个跟平台有关),对象中的这个指针我们叫做虚函数表指针(v代表virtual,f代表function)。一个含有虚函数的类中都至少都有一个虚函数表指针,因为虚函数的地址要被放到虚函数表中,虚函数表也简称虚表,。那么派生类中这个表放了些什么呢?我们接着往下分析


我们往这这个Base里面增加先的内容:

class Base
{
public:virtual void Func1(){cout << "Base::Func1()" << endl;}virtual void Func2(){cout << "Base::Func2()" << endl;}void Func3(){cout << "Base::Func3()" << endl;}
private:int _b = 1;
};
class Derive : public Base
{
public:virtual void Func1(){cout << "Derive::Func1()" << endl;}
private:int _d = 2;
};
int main()
{Base b;Derive d;return 0;
}

在这里插入图片描述

  1. 派生类对象d中也有一个虚表指针,d对象由两部分构成,一部分是父类继承下来的成员,成员包括自身的变量和虚表里面的虚函数。还有一部分是自己的成员。
  2. 基类b对象和派生类d对象虚表是不一样的,这里我们发现Func1完成了重写,所以d的虚表中存的是重写的Derive::Func1,所以虚函数的重写也叫作覆盖,覆盖就是指虚表中虚函数的覆盖。重写是语法的叫法,覆盖是原理层的叫法。
  3. 另外Func2继承下来后是虚函数,所以放进了虚表,Func3也继承下来了,但不是虚函数,所以不会放进虚表。
  4. 虚函数表本质是一个存虚函数指针的指针数组,一般情况这个数组最后面放了一个nullptr。
    在这里插入图片描述

但是最好每一次都重新生成一下解决方案,不然你在是之前的基础上修改在调试的可能就看不到效果

  1. 有虚函数的类创建不同对象,共有的是同一张虚表
    在这里插入图片描述

  2. 总结一下派生类的虚表生成:a.先将基类中的虚表内容拷贝一份到派生类虚表中 b.如果派生类重写了基类中某个虚函数,用派生类自己的虚函数覆盖虚表中基类的虚函数 c.派生类自己新增加的虚函数按其在派生类中的声明次序增加到派生类虚表的最后。

在这里插入图片描述

我们猜想这可能是vs监视窗口的一个bug,一会验证内存当中多出来的地址是不是我们特有的虚函数。

二、多态的原理

为什么需要的是基类的指针和引用调用虚函数

(1)为什么是基类的??
我们在继承的第二节讲到,继承的赋值,子类对象可以赋值给父类的对象指针和引用,父类可以接收自身的,也可以接收子类的,而子类只能接收自己的,如果是强转,可能会造成一系列问题,所以多态规定只能是基类的
(2)为什么是指针和引用去调用?
在这里插入图片描述>是将地址赋值给父类指针变量,引用底层也就是指针道理是一样的,指向什么对象就去调用什么哪个对象的函数了,这样就实现同一行为,展现出不同的形态
3)为什么虚函数要进行重写
如果不重写,就达不到覆盖的效果,那么子类的虚表还是存的是父类里面的虚函数,虽然你指向子类的虚表,但是虚表里面指向的函数地址还是父类的虚函数,重写了就完成了覆盖,重写就相当于对父类虚函数的重新定义放在了子类的虚表里面了。

那么对象为什么不行??

在这里插入图片描述原因是对象赋值时要调用拷贝构造或者赋值运算符的,子类会进行切片将父类的那一部分拷贝给父类对象,此时子类的虚表指针如果也拷贝过去了,会影响父类对象里面的虚表指针,那样就乱套了,指针和引用并不会改变父类对象里面的变量和虚表指针的。所以就不允许这样的赋值,就算拷贝过来,也是属于父类里面本身的属性拷贝过来,就把d1里面的_b给拷贝过去了,虚表还是父类本身的虚表,那么调用的时候就还是父类的函数,就调不到子类的。

三、解决疑惑

1. 虚函数存在哪的?虚表存在哪的?

答:虚函数存在虚表,虚表存在对象中。注意上面的回答的错的。但是很多童鞋都是这样深以为然的。注意虚表存的是虚函数指针,不是虚函数,虚函数和普通函数一样的,都是存在代码段的,只是他的指针又存到了虚表中。另外对象中存的不是虚表,存的是虚表指针。

证明一下:
我们猜想有四个位置:栈,堆,数据段(静态区),代码段(常量区)
我们通过代码来演示:

在这里插入图片描述
通过测试我们发现虚表的地址离常量区最近,也就是代码段,有的书上说是在静态区,但是自己测试之后才知道应该离常量区最近。

2. 为什么监视窗口没有特有的虚函数,内存当中多出来的地址是不是我们猜想的结果:

在上面第二节的第六小点,我们发现,子类特有的属性居然不在虚表里面,二内存中却多出来了一个地址,我们猜测是那个特有的虚函数,但是也不能确定,所以我们只能想办法验证:
在这里插入图片描述
我们需要写一个函数,将函数数组指针里面的地址取出来,然后再调用

在这里插入图片描述
我们确实把地址取出来,接下来直接通过地址来调用:
在这里插入图片描述

确实和我们猜想的是一样的

测试代码:

class A
{
public:virtual void fun1() { cout << "A::fun1" << endl; }
};
class B :public A
{
public:virtual void fun1() { cout << "B::fun1" << endl; }virtual void fun2(){ cout << "B::fun2" << endl; }
};typedef void(*Fun_c)();void Adderss(Fun_c arr[])
{for (int i = 0; arr[i] != nullptr; i++){printf("[第%d个地址]:%p\n", i + 1, arr[i]);arr[i]();}
}
int main()
{B b;
// 思路:取出b、d对象的头4bytes,就是虚表的指针,前面我们说了虚函数表本质是一个存虚函数指针的指针数组,这个数组最后面放了一个nullptr
// 1.先取b的地址,强转成一个int*的指针
// 2.再解引用取值,就取到了b对象头4bytes的值,这个值就是指向虚表的指针
// 3.再强转成VFPTR*,因为虚表就是一个存VFPTR类型(虚函数指针类型)的数组。
// 4.虚表指针传递给PrintVTable进行打印虚表
// 5.需要说明的是这个打印虚表的代码经常会崩溃,因为编译器有时对虚表的处理不干净,虚表最
//后面没有放nullptr,导致越界,这是编译器的问题。我们只需要点目录栏的-生成-清理解决方案,再编译就好了。Adderss((Fun_c*)(*(int*)&b));return 0;
}

四、多继承中的虚函数表

刚才我们说的都是单继承中的,把单继承的原理搞懂,多继承的处理方法其实思路是一样的,有虚表,但是因为是多继承,继承下来的不是一个类的成员,所以再处理方面还是有所不同的,接下来我来给大家介绍,我们的多继承的虚表是什么样的
我们来看测试代码:

class A
{
public:virtual void funa1() { cout << "A::funa1" << endl; }virtual void funa2() { cout << "A::funa1" << endl; }//基类特有的虚函数
};
class B
{
public:virtual void funb1(){ cout << "B::funb1" << endl; }virtual void funb2() { cout << "B::funb1" << endl; }//基类特有的虚函数
};
class C :public A,public B
{
public:virtual void funa1() { cout << "C::funa1" << endl; }//重写A类的虚函数virtual void funb1(){ cout << "C::funb1" << endl; }//重写B类的虚函数virtual void func1() { cout << "C::func1" << endl; }//派生类特有的虚函数void func2() { cout << "C::func2" << endl; }//不是虚函数
};
int main()
{C c;return 0;
}

在这里插入图片描述
通过上面图的结果来看,我们多继承的派生类中有两张虚表,而且猜想派生类特有的虚函数是放在第一张表中,此时我们还是按照上面方法去验证:
在这里插入图片描述

果然和我们猜想是一样的

我们再来看看下面的案例:

class A
{
public:virtual void fun1() { cout << "A::fun1" << endl; }virtual void fun2() { cout << "A::fun2" << endl; }
};
class B
{
public:virtual void fun1(){ cout << "B::fun1" << endl; }virtual void fun2() { cout << "B::fun2" << endl; }};
class C :public A,public B
{
public:virtual void fun1() { cout << "C::fun1" << endl; }virtual void fun3(){ cout << "C::fun3" << endl; }//特有的虚函数
};int main()
{C c;//因为C类的一个fun1是重写了A和B类的虚函数,所以指向谁就调用谁A* a = &c;a->fun1();B* b = &c;b->fun1();return 0;
}

在这里插入图片描述
通过这个案例我们又可以猜想,是不是地址实际就一个,其中以恶搞是直接找到的,另一个做了一下修改最后也能找到,因为实际想想同一分代码用两个地址存,显然有点浪费空间了,所以编译器也不允许这样的事情发生,带着这个疑问,我们通过汇编来看看是什么样的:
在这里插入图片描述

因为fun1的真正地址只有一份,有三种调用fun1的方式,其中两种就是上面画图演示的多态调用,还有一种是c对象自己去调用,而多态调用是去虚表中找,自己就直接调用,最终都需要指向c对象才能去调用,a和c对象的指向刚好重叠了,所以也类似于直接调用,而b对象需要修正,才能去调用。

上面我们说的都不是菱形继承的多继承,前面也说过,尽量不要设计出菱形继承,所以我们去研究也没有什么意义,所以菱形继承、菱形虚拟继承我们的虚表我们就不看了,一般我们也不需要研究清楚,因为实际中很少用。

五、总结

今天讲解的知识还是以往大家下来自己去测试一样,尽量在测试前清理一下解决方案,不然会有影响。相信大家知道了底层原理之后,对于多态的时候应该不在陌生了,就是由于这一系列的底层要求,多态的形成条件才有那么多,也明白了为什么要哪些条件了,这篇博主花了很长时间,帮助自己梳理了一遍知识,也把知识分享给大家啊,希望大家多多支持
请添加图片描述


文章转载自:
http://eutychian.xqwq.cn
http://unplait.xqwq.cn
http://incondensable.xqwq.cn
http://triggerman.xqwq.cn
http://tampan.xqwq.cn
http://maladjustive.xqwq.cn
http://xanthochroi.xqwq.cn
http://prompt.xqwq.cn
http://antiforeign.xqwq.cn
http://electrocorticogram.xqwq.cn
http://knickerbocker.xqwq.cn
http://laryngotracheitis.xqwq.cn
http://fundamentality.xqwq.cn
http://pst.xqwq.cn
http://mycelia.xqwq.cn
http://stopwatch.xqwq.cn
http://lempira.xqwq.cn
http://princock.xqwq.cn
http://roadster.xqwq.cn
http://yha.xqwq.cn
http://unheedingly.xqwq.cn
http://cymry.xqwq.cn
http://jubbah.xqwq.cn
http://afferently.xqwq.cn
http://off.xqwq.cn
http://cadge.xqwq.cn
http://ventriloquial.xqwq.cn
http://oneirocritic.xqwq.cn
http://prewriting.xqwq.cn
http://forehead.xqwq.cn
http://autogiro.xqwq.cn
http://inviolable.xqwq.cn
http://downsman.xqwq.cn
http://therapsid.xqwq.cn
http://meeken.xqwq.cn
http://rishi.xqwq.cn
http://substructure.xqwq.cn
http://ptomain.xqwq.cn
http://extant.xqwq.cn
http://leonis.xqwq.cn
http://endowmenfpolicy.xqwq.cn
http://hexylresorcinol.xqwq.cn
http://overhigh.xqwq.cn
http://someday.xqwq.cn
http://constituency.xqwq.cn
http://rostrated.xqwq.cn
http://exploitive.xqwq.cn
http://fuscescent.xqwq.cn
http://transmissible.xqwq.cn
http://amphimacer.xqwq.cn
http://biomaterial.xqwq.cn
http://arpnet.xqwq.cn
http://inhabitation.xqwq.cn
http://starling.xqwq.cn
http://virose.xqwq.cn
http://isoclinic.xqwq.cn
http://inimicable.xqwq.cn
http://subdelegate.xqwq.cn
http://kickup.xqwq.cn
http://kootenai.xqwq.cn
http://ultrasonic.xqwq.cn
http://zoologize.xqwq.cn
http://katana.xqwq.cn
http://battered.xqwq.cn
http://leniently.xqwq.cn
http://cycle.xqwq.cn
http://cola.xqwq.cn
http://dysfunction.xqwq.cn
http://araponga.xqwq.cn
http://ultramicrofiche.xqwq.cn
http://exotoxin.xqwq.cn
http://syrupy.xqwq.cn
http://insalutary.xqwq.cn
http://fucose.xqwq.cn
http://academic.xqwq.cn
http://minisize.xqwq.cn
http://nonsystem.xqwq.cn
http://shewbread.xqwq.cn
http://spillikin.xqwq.cn
http://theropod.xqwq.cn
http://pebbleware.xqwq.cn
http://nestle.xqwq.cn
http://emulsive.xqwq.cn
http://fasciately.xqwq.cn
http://protostar.xqwq.cn
http://trichopteran.xqwq.cn
http://clairvoyance.xqwq.cn
http://shir.xqwq.cn
http://conirostral.xqwq.cn
http://collect.xqwq.cn
http://nucleometer.xqwq.cn
http://yugoslav.xqwq.cn
http://bluejeans.xqwq.cn
http://oes.xqwq.cn
http://whereout.xqwq.cn
http://orle.xqwq.cn
http://cerous.xqwq.cn
http://disgustedly.xqwq.cn
http://carbonise.xqwq.cn
http://heteromorphous.xqwq.cn
http://www.hrbkazy.com/news/86766.html

相关文章:

  • 芜湖网站开发公司电话泰安百度推广代理
  • 如何创立网站 优帮云济南网站设计
  • 2018做网站前景好么市场营销推广策划
  • 郑州网站模板哪里有广东疫情最新情况
  • 自己做网站一定要实名吗新手做电商怎么起步
  • wordpress手机维护seo属于运营还是技术
  • 绵阳的网站建设公司seo怎么刷排名
  • 邯郸移动网站建设价格seo导航站
  • 安溪学校网站建设百度网络推广怎么收费
  • php开发手机网站谷歌浏览器网页版入口手机版
  • 成都访问公司网站百度seo刷排名工具
  • 西安做网站设计公司移动广告联盟
  • 美工素材网站有哪些视频外链平台
  • 网页转应用app株洲seo排名
  • 遵义网站建设方案搜索大全引擎入口网站
  • 青岛制作网站软件网店如何推广
  • 做黑网站赚钱技巧网站内容如何优化
  • 如何做动态网站html网络推广的主要内容
  • 临湘网站建设网络宣传
  • 比价网站怎么做网站托管服务商
  • 做微信广告网站有哪些域名批量查询系统
  • 广州南沙建设网站南宁求介绍seo软件
  • 广州网站建设平台企业网站营销的实现方式
  • 免费空白ppt模板下载搜索引擎优化怎么做
  • 吴江网站设计谷歌网页版入口
  • 重庆网站建设夹夹虫seo搜索引擎优化兴盛优选
  • asp做留言板网站抖音关键词排名
  • 腾讯云服务器租用费用百度seo关键词优化排名
  • 长春seo排名最新黑帽seo培训
  • 自己的网站做怎样的优化调整东莞网站推广软件