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

网站建立项目步骤企业网站建设的流程与原则

网站建立项目步骤,企业网站建设的流程与原则,研究院网站系统建设方案,门户网站建设经济交流材料目录 深入理解C 虚函数表虚函数表概述单继承下的虚函数表派生类未覆盖基类虚函数派生类覆盖基类虚函数多继承下的虚函数表无虚函数覆盖派生类覆盖基类虚函数钻石型虚继承总结几个原则安全性问题深入理解C 虚函数表 ​ C中的虚函数的作用主要是实现了多态的机制。关于多态#… 目录 深入理解C 虚函数表虚函数表概述单继承下的虚函数表派生类未覆盖基类虚函数派生类覆盖基类虚函数多继承下的虚函数表无虚函数覆盖派生类覆盖基类虚函数钻石型虚继承总结几个原则安全性问题 深入理解C 虚函数表 ​ 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语义操作会有一定的隐患当我们使用时要注意这些危险的东西 参考 https://coolshell.cn/articles/12165.html https://jocent.me/2017/08/07/virtual-table.html https://blog.csdn.net/lihao21/article/details/50688337转载于:https://www.cnblogs.com/Mered1th/p/10924545.html
http://www.zqtcl.cn/news/677496/

相关文章:

  • 网站开发中文摘要当今做啥网站致富
  • 钓鱼网站制作方法WordPress音乐免刷新
  • 北京网站建设的公网站订票策划方案
  • 做搜狗网站快速排名福田瑞沃自卸车
  • 帮人做图挣外快的网站做网站刷流量挣钱吗
  • 网站改版被降权从0到建网站
  • dedese网站牛客网官网
  • 网站到期续费要多少钱如何做一个电商
  • 试述网站建设的步骤石家庄公司网站如何制作
  • 百度推广自己做网站吗韶关东莞网站建设
  • 濮阳建站建设室内设计效果图图片
  • 上海找做网站公司国外网站国内做好还是国外做
  • 一个vps建两个网站怎么弄数据库济南地产行业网站开发
  • 网站到期请续费站长网
  • 个人网站名字可以用哪些促销网站怎么做
  • 网站开发需要提供哪些东西镇江网络违法网站
  • 都江堰建设局官方网站wordpress分享此文章
  • 素材网站整站下载赣州网站建设信息
  • 网上做问卷报酬不错的网站是iis 如何新建网站
  • 济南建设监理协会网站雄安网站建设单位
  • 微网站模板怎么用公司网站无法打开
  • 查询网站备案进度做外贸的数据网站
  • 广州建网站哪儿济南兴田德润简介室内设计效果图手绘图
  • 网站页面设计要求做搜狗网站优化
  • 家纺代发网站建设百度怎么做开锁网站
  • 哈尔滨网站建设有哪些做互联网项目怎么推广
  • 网站首页代码怎么做温州设计集团有限公司官网
  • 如何更换网站图片自己做头像的网站漫画
  • 网站设计风格确认书网站标题 没有排名
  • iis内网站设置允许脚本执行免费行情100个软件