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

php 网站 整合 数据库快速搭建网站前端插件

php 网站 整合 数据库,快速搭建网站前端插件,注册网站需要多少钱?,常州做网站公司哪家好【1】表现形式:同样的调用语句有多种不同的表现形态 【2】分类:静态联编和动态联编 静态联编有函数重载(运算符重载是特殊的函数重载),模板 【3】重点说下动态联编 【3.1】动态联编的实现需要以下步骤: 有继承关系、父类函数有virtual关…

【1】表现形式:同样的调用语句有多种不同的表现形态

【2】分类:静态联编和动态联编

静态联编有函数重载(运算符重载是特殊的函数重载),模板

【3】重点说下动态联编

【3.1】动态联编的实现需要以下步骤:

  1. 有继承关系、
  2. 父类函数有virtual关键字
  3. 子类对父类对虚函数进行重写
  4. 父类的指针(引用)指向子类对象
  5. 通过父类的指针调用虚方法触发多态

【3.2】动态联编的编译器实现原理

当类中声明虚函数时,编译器会在类中生成一个虚函数表

虚函数表是一个存储类成员函数指针的数据结构

虚函数表是由编译器自动生成与维护的

virtual成员函数会被编译器放入虚函数表中 

存在虚函数时,够造对象时,对象中都有一个指向虚函数表的指针(vfptr指针) 

Vfptr   virtual function pointer 

如我们有下面的这个函数:

Class parent

{

Public:

Virtual func();

}

Class son:public parent

{

Public:

Virtual func();

}

void run(parent*p)

{

p->func();

}

编译器来确定func是否为虚函数

a.如果不是虚函数,编译器可以直接确定调用的函数,静态联编,根据parent类型来确定,编译完成之后就知道调用哪个函数地址了。

b.如果是虚函数,编译器根据对象p的vptr指针,所指的虚函数表中查找func函数,并调用,查找和调用时在执行时完成,动态联编。

说明1:

通过虚函数表指针VFPTR调用重写函数是在程序运行时进行的,因此需要通过寻址操作才能确定真正应该调用的函数。而普通成员函数是在编译时就确定了调用的函数。在效率上,虚函数的效率要低很多。

说明2:

出于效率考虑,没有必要将所有成员函数都声明为虚函数

这里先给出一个图片来简单表示下,单继承的情况下,虚函数表的由来:

再给出一个证明虚函数的例子,以及探究虚函数表内部机构的例子:

参考链接:C++ 虚函数表解析---陈皓改进版_啊大1号的博客-CSDN博客_虚表 陈皓

#include<iostream>
using namespace std;
class Base {public:virtual void f() { cout << "Base::f" << endl; }virtual void g() { cout << "Base::g" << endl; }virtual void h() { cout << "Base::h" << endl; }
};typedef void(*Fun)(void);/*事实上,楼主写的一开始就是错的,虚函数表是类对象之间共享的,* 而非每个对象都保存了一份,楼主得到的也只是虚指针的地址,* 而非虚函数表的地址,事实上对虚函数指针的地址解引用得到的才* 是虚函数表的地址(因为虚函数指针指向虚函数表),以上经过理论和实际验证。
MyClass mc;//奇技淫巧、用int*只是因为32位系统中指针大小跟int相同//  pFun = (Fun)*( (int*)*(int*)(&mc)+1);//跟下面一样auto a1 = (int*)&mc;//找到虚指针的位置(地址)auto a2 = *a1;//得到虚指针的内容(指向的虚表的地址)auto a3 = (int*)a2;//得到虚表的地址pFun = (Fun)*(a3+1);//偏移得到虚表中某个虚函数的地址,解引用得到函数本身pFun();* */int main(){//虚函数表是用这个数组实现的 现在已经确定了cout<<sizeof(int)<<sizeof(long long)<<endl;Base b;Fun pFun = NULL;cout << "虚函数(表)指针 地址:" << (long long *)(&b) << endl;cout << "虚函数表 — 的地址:" << (long long*)*(long long *)(&b) << endl;
// Invoke the first virtual function// 这里才得到第一个虚函数的地址pFun = (Fun)*((long long *)*(long long *)(&b)+0);pFun();pFun = (Fun)*((long long *)*(long long *)(&b)+1);pFun();pFun = (Fun)*((long long *)*(long long *)(&b)+2);pFun();
}

这个时候你应该懂了吧。什么?还是有点晕。也是,这样的代码看着太乱了。没问题,让我画个图解释一下。如下所示:

注意:在上面这个图中,我在虚函数表的最后多加了一个结点,这是虚函数表的结束结点,就像字符串的结束符'\0'一样,其标志了虚函数表的结束。这个结束标志的值在不同的编译器下是不同的。在WinXP+VS2003下,这个值是NULL。而在Ubuntu 7.10 + Linux 2.6.22 + GCC 4.1.3下,这个值如果是1,表示还有下一个虚函数表,如果值是0,表示是最后一个虚函数表。

下面,我将分别说明“无覆盖”和“有覆盖”时的虚函数表的样子。没有覆盖父类的虚函数是毫无意义的。我之所以要讲述没有覆盖的情况,主要目的是为了给一个对比。在比较之下,我们可以更加清楚地知道其内部的具体实现。

一般继承(无虚函数覆盖)

下面,再让我们来看看继承时的虚函数表是什么样的。假设有如下所示的一个继承关系:

请注意,在这个继承关系中,子类没有重载任何父类的函数。那么,在派生类的实例中,其虚函数表如下所示:

对于实例:Derive d; 的虚函数表如下:

我们可以看到下面几点:

1)虚函数按照其声明顺序放于表中。

2)父类的虚函数在子类的虚函数前面。

我相信聪明的你一定可以参考前面的那个程序,来编写一段程序来验证。

 一般继承(有虚函数覆盖)

 覆盖父类的虚函数是很显然的事情,不然,虚函数就变得毫无意义。下面,我们来看一下,如果子类中有虚函数重载了父类的虚函数,会是一个什么样子?假设,我们有下面这样的一个继承关系。

为了让大家看到被继承过后的效果,在这个类的设计中,我只覆盖了父类的一个函数:f()。那么,对于派生类的实例,其虚函数表会是下面的一个样子:

 

我们从表中可以看到下面几点,

1)覆盖的f()函数被放到了虚表中原来父类虚函数的位置。

2)没有被覆盖的函数依旧。

这样,我们就可以看到对于下面这样的程序,

    Base *b = new Derive();b->f();

由b所指的内存中的虚函数表的f()的位置已经被Derive::f()函数地址所取代,于是在实际调用发生时,是Derive::f()被调用了。这就实现了多态。

 

 

 

 

http://www.yayakq.cn/news/338127/

相关文章:

  • 常营网站建设聊城做手机网站
  • 亚马逊网站建设进度计划书装饰设计效果图
  • 怎么联系做网站公司苏州官网设计
  • 西安竞价托管公司网站优化排名易下拉用法
  • 免费建设网站的好么织梦做的网站后台怎么进
  • 织梦网站在服务器上传图片北京建设注册中心网站首页
  • 做视频上传可以赚钱的网站在哪个网站可以查做项目中标的
  • 张掖网站设计公司网站群系统建设标准
  • delphi 可做网站吗网站推广在哪好外贸
  • 网站建设与管理实践实践报告淘宝每平每屋设计家官网
  • 防城港装修公司口碑排行哪有培训seo
  • 长春做网站wordpress防站
  • 网站建设设计logo网页版传奇服务端
  • 如何制作网站平台营销型旅游网站建设
  • 安徽美丽乡村建设网站智慧团建官网登录入口电脑版
  • 建设部网站撤销注册资质的都是公职人员吗网页制作基础教程笔记
  • 永康住房城乡建设局网站成都网络公司服务内容
  • 网站建设公司华网天下买2年送2年中国电商平台
  • 查看网站百度排名哈尔滨网络公司营销机构
  • 金华网站建设公司排名廊坊网站推广外包
  • 网站首页该怎么做建站网络
  • 可免费商用的cms建站系统生鲜网站模板
  • 佛山网站建设开发团队外包加工网免押金
  • 网站访客qq系统怎么进入自己网站主机地址
  • 免费行情软件网站下载安装互联网营销有哪些
  • 做我男朋友好不好网站哈尔滨网站设计公司
  • 地板网站模板gate网站合约怎么做空
  • 网站建设 天佩营销四川住建管理平台官网
  • 南阳专业网站排名推广网站域名空间怎么买
  • 网站处于建设中会显示什么英文淘宝客做动态广告的网站