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

天元建设集团有限公司 安百平 电话网站seo流程

天元建设集团有限公司 安百平 电话,网站seo流程,网站栏目做跳转,类似建E网模型网站建设点击蓝字关注我们深入理解C 虚函数表C中的虚函数的作用主要是实现了多态的机制。关于多态#xff0c;简而言之就是用父类型别的指针指向其子类的实例#xff0c;然后通过父类的指针调用实际子类的成员函数。Derive d; Base1 *b1 d; Base2 *b2 d; Base3 *b3 虚函数表C中的虚函数的作用主要是实现了多态的机制。关于多态简而言之就是用父类型别的指针指向其子类的实例然后通过父类的指针调用实际子类的成员函数。Derive d; Base1 *b1 d; Base2 *b2 d; Base3 *b3 d; b1-f(); //Derive::f() b2-f(); //Derive::f() b3-f(); //Derive::f()b1-g(); //Base1::g() b2-g(); //Base2::g() b3-g(); //Base3::g()这种技术可以让父类的指针有“多种形态”这是一种泛型技术。所谓泛型技术说白了就是试图使用不变的代码来实现可变的算法。比如模板技术RTTI技术虚函数技术要么是试图做到在编译时决议要么试图做到运行时决议。本文将详细介绍虚函数表的实现及其内存布局。虚函数表概述虚函数表是指在每个包含虚函数的类中都存在着一个函数地址的数组。当我们用父类的指针来操作一个子类的时候这张虚函数表指明了实际所应该调用的函数。C的编译器保证虚函数表的指针存在于对象实例中最前面的位置这样通过对象实例的地址得到这张虚函数表然后就可以遍历其中函数指针并调用相应的函数。按照上面的说法来看一个实际的例子#include iostreamusing namespace std;class Base { public:virtual void f() { cout f() endl; }virtual void g() { cout g() endl; }virtual void h() { cout h() endl; } };int main() {Base t;( ((void(*)())*((int*)(*((int*)t)) 0)) ) ();( ((void(*)())*((int*)(*((int*)t)) 1)) ) ();( ((void(*)())*((int*)(*((int*)t)) 2)) ) ();return 0; }经过VS2017x86测试我们成功地通过实例对象的地址得到了对象所有的类函数。main定义Base类对象t把b转成int *取得虚函数表的地址vtptr就是(int*)(t)然后再解引用并强转成int * 得到第一个虚函数的地址也就是Base::f()即(int*)(*((int*)t))那么第二个虚函数g()的地址就是(int*)(*((int*)t)) 1依次类推。单继承下的虚函数表派生类未覆盖基类虚函数下面我们来看下派生类没有覆盖基类虚函数的情况其中Base类延用上一节的定义。从图中可看出虚函数表中依照声明顺序先放基类的虚函数地址再放派生类的虚函数地址。可以看到下面几点1虚函数按照其声明顺序放于表中。2父类的虚函数在子类的虚函数前面。测试代码#include iostreamusing namespace std;class Base { public:virtual void f() { cout f() endl; }virtual void g() { cout g() endl; }virtual void h() { cout h() endl; } };class Devired :public Base{ public:virtual void x() { cout x() endl; } };int main() {Devired t;(((void(*)()) *((int*)(*((int*)t))))) ();(((void(*)())*((int*)(*((int*)t)) 1))) ();(((void(*)())*((int*)(*((int*)t)) 2))) ();//(((void(*)())*((int*)(*((int*)t)) 3))) ();return 0; }测试效果派生类覆盖基类虚函数再来看一下派生类覆盖了基类的虚函数的情形可见虚表中派生类覆盖的虚函数的地址被放在了基类相应的函数原来的位置 显然的不然虚函数失去意义派生类没有覆盖的虚函数延用基类的测试代码#include iostreamusing namespace std;class Base { public:virtual void f() { cout f() endl; }virtual void g() { cout g() endl; }virtual void h() { cout h() endl; } };class Derive :public Base{ public:virtual void x() { cout x() endl; }virtual void f() { cout Derive::f() endl; } };int main() {Derive t;(((void(*)()) *((int*)(*((int*)t))))) ();(((void(*)())*((int*)(*((int*)t)) 1))) ();(((void(*)())*((int*)(*((int*)t)) 2))) ();//(((void(*)())*((int*)(*((int*)t)) 3))) ();return 0; }测试效果多继承下的虚函数表无虚函数覆盖如果是多重继承的话问题就变得稍微复杂一丢丢主要有几点每个基类都有自己的虚函数表派生类的虚函数地址存依照声明顺序放在第一个基类的虚表最后这点和单继承无虚函数覆盖相同具体见下图所示测试代码#include iostream class Base { public:Base(int mem1 1, int mem2 2) : m_iMem1(mem1), m_iMem2(mem2) { ; }virtual void vfunc1() { std::cout In vfunc1() std::endl; }virtual void vfunc2() { std::cout In vfunc2() std::endl; }virtual void vfunc3() { std::cout In vfunc3() std::endl; }private:int m_iMem1;int m_iMem2; };class Base2 { public:Base2(int mem 3) : m_iBase2Mem(mem) { ; }virtual void vBase2func1() { std::cout In Base2 vfunc1() std::endl; }virtual void vBase2func2() { std::cout In Base2 vfunc2() std::endl; }private:int m_iBase2Mem; };class Base3 { public:Base3(int mem 4) : m_iBase3Mem(mem) { ; }virtual void vBase3func1() { std::cout In Base3 vfunc1() std::endl; }virtual void vBase3func2() { std::cout In Base3 vfunc2() std::endl; }private:int m_iBase3Mem; };class Devired : public Base, public Base2, public Base3 { public:Devired(int mem 7) : m_iMem1(mem) { ; }virtual void vdfunc1() { std::cout In Devired vdfunc1() std::endl; }private:int m_iMem1; };int main() {// Test_3Devired d;int *dAddress (int*)d;typedef void(*FUNC)();/* 1. 获取对象的内存布局信息 */// 虚表地址一int *vtptr1 (int*)*(dAddress 0);int basemem1 (int)*(dAddress 1);int basemem2 (int)*(dAddress 2);int *vtpttr2 (int*)*(dAddress 3);int base2mem (int)*(dAddress 4);int *vtptr3 (int*)*(dAddress 5);int base3mem (int)*(dAddress 6);/* 2. 输出对象的内存布局信息 */int *pBaseFunc1 (int *)*(vtptr1 0);int *pBaseFunc2 (int *)*(vtptr1 1);int *pBaseFunc3 (int *)*(vtptr1 2);int *pBaseFunc4 (int *)*(vtptr1 3);(FUNC(pBaseFunc1))();(FUNC(pBaseFunc2))();(FUNC(pBaseFunc3))();(FUNC(pBaseFunc4))();// .... 后面省略若干输出内容可自行补充return 0; }测试效果派生类覆盖基类虚函数我们再来看一下派生类覆盖了基类的虚函数的情形可见虚表中派生类覆盖的虚函数的地址被放在了基类相应的函数原来的位置派生类没有覆盖的虚函数延用基类的代码如下所示注意这里只给出了类的定义main函数的测试代码与上节一样class Devired : public Base, public Base2, public Base3 { public:Devired(int mem 7) : m_iMem1(mem) { ; }virtual void vdfunc1() { std::cout In Devired vdfunc1() std::endl; }virtual void vfunc1() { std::cout In Devired vfunc1() std::endl; }virtual void vBase2func1() { std::cout In Devired vfunc1() std::endl; }private:int m_iMem1; };测试效果钻石型虚继承该继承还是遵循上述的所有原则我们直接来测试。测试代码// 测试四钻石型虚继承//虚基指针所指向的虚基表的内容 // 1. 虚基指针的第一条内容表示的是该虚基指针距离所在的子对象的首地址的偏移 // 2. 虚基指针的第二条内容表示的是该虚基指针距离虚基类子对象的首地址的偏移#pragma vtordisp(off) #include iostream using std::cout; using std::endl;class B { public:B() : _ib(10), _cb(B) {}virtual void f(){cout B::f() endl;}virtual void Bf(){cout B::Bf() endl;}private:int _ib;char _cb; };class B1 : virtual public B { public:B1() : _ib1(100), _cb1(1) {}virtual void f(){cout B1::f() endl;}#if 1virtual void f1(){cout B1::f1() endl;}virtual void Bf1(){cout B1::Bf1() endl;} #endifprivate:int _ib1;char _cb1; };class B2 : virtual public B { public:B2() : _ib2(1000), _cb2(2) {}virtual void f(){cout B2::f() endl;} #if 1virtual void f2(){cout B2::f2() endl;}virtual void Bf2(){cout B2::Bf2() endl;} #endif private:int _ib2;char _cb2; };class D : public B1, public B2 { public:D() : _id(10000), _cd(3) {}virtual void f(){cout D::f() endl;}#if 1virtual void f1(){cout D::f1() endl;}virtual void f2(){cout D::f2() endl;}virtual void Df(){cout D::Df() endl;} #endif private:int _id;char _cd; };int main(void) {D d;cout sizeof(d) endl;return 0; }测试效果1class D size(52): 1 --- 1 0 | --- (base class B1) 1 0 | | {vfptr} 1 4 | | {vbptr} 1 8 | | _ib1 112 | | _cb1 1 | | alignment member (size3) 1 | --- 116 | --- (base class B2) 116 | | {vfptr} 120 | | {vbptr} 124 | | _ib2 128 | | _cb2 1 | | alignment member (size3) 1 | --- 132 | _id 136 | _cd 1 | alignment member (size3) 1 --- 1 --- (virtual base B) 140 | {vfptr} 144 | _ib 148 | _cb 1 | alignment member (size3) 1 --- 1 1D::$vftableB1: 1 | D_meta 1 | 0 1 0 | D::f1 1 1 | B1::Bf1 1 2 | D::Df 1 1D::$vftableB2: 1 | -16 1 0 | D::f2 1 1 | B2::Bf2 1 1D::$vbtableB1: 1 0 | -4 1 1 | 36 (Dd(B14)B) 1 1D::$vbtableB2: 1 0 | -4 1 1 | 20 (Dd(B24)B) 1 1D::$vftableB: 1 | -40 1 0 | D::f 1 1 | B::Bf 1总结几个原则单继承虚表中派生类覆盖的虚函数的地址被放在了基类相应的函数原来的位置派生类没有覆盖的虚函数就延用基类的。同时虚函数按照其声明顺序放于表中父类的虚函数在子类的虚函数前面。多继承每个基类都有自己的虚函数表派生类的虚函数地址存依照声明顺序放在第一个基类的虚表最后安全性问题当我们直接通过父类指针调用子类中的未覆盖父类的成员函数编译器会报错但通过实验我们可以用对象的地址访问到各个子类的成员函数就违背了C语义操作会有一定的隐患当我们使用时要注意这些危险的东西*声明本文于网络整理版权归原作者所有如来源信息有误或侵犯权益请联系我们删除或授权事宜。戳“阅读原文”我们一起进步
http://www.pierceye.com/news/192232/

相关文章:

  • 免费整套ppt模板下载网站东莞建设教育网站
  • 漯河网站建设漯河ps制作个人网站首页
  • 电商网站公司软件开发和软件研发
  • 网站建设浙江公司网站开发运营新人要注意什么
  • 外贸网站模板哪里下载家里电脑可以做网站服务器吗
  • 长沙门户网站北京设计网站的公司
  • 站长统计平面设计找工作难吗
  • seo建站公司推荐电商平台活动策划方案
  • 建设淘宝客网站.lc和ev手机对比平台
  • vue 做企业网站特产网站开发背景
  • 奉新网站制作dede视频网站源码
  • 做动画网站去哪采集建设网站需要的资金清单
  • 网站后台发邮件注册公司需要什么证件和手续
  • 炫酷特效网站万网虚拟主机免费空间
  • 公司网站模板最新怀远网站建设哪家好
  • 交互式网站定义如何网上找加工订单
  • 一个域名可以做几个网站吗南城网站建设公司
  • 宝安商城网站建设flash新手入门简单动画制作
  • 设置网站建设WordPress adsen
  • 网站与微信内容建设与运维总结建筑网络图
  • 网站模板文件不存在网站建设礻金手指下拉十二
  • 东莞浩智建设网站公司做百度推广员赚钱吗
  • qq网站推广代码昆明哪里做网站
  • 章丘营销型网站设计公司青岛网络优化排名
  • 制作网站模板的发展空间wordpress 阿里云 cdn
  • 交互式网站备案万网域名网站建设
  • 备案 个人网站名称月坛网站建设公司
  • 网站建设要解决哪些方面的事项临海外发加工网
  • 甜品店网站开发背景江宁区住房建设局网站
  • asp.net网站开发视频教程找能做网站的