虚函数表的问题
来源:互联网 发布:深q网络模型 编辑:程序博客网 时间:2024/06/01 12:30
虚函数表:
多态是由虚函数实现的,而虚函数主要是通过虚函数表(V-Table)来实现的。
如果一个类中包含虚函数(virtual修饰的函数),那么这个类就会包含一张虚函数表,虚函数表存储的每一项是一个虚函数的地址。如下图:
这个类的每一个对象都会包含一个虚指针(虚指针存在于对象实例地址的最前面,保证虚函数表有最高的性能),这个虚指针指向虚函数表。
注:对象不包含虚函数表,只有虚指针,类才包含虚函数表,派生类会生成一个兼容基类的虚函数表。
· 原始基类的虚函数表:
下图是原始基类的对象,可以看到虚指针在地址的最前面,指向基类的虚函数表(假设基类定义了3个虚函数)
· 单继承时的虚函数(无重写基类虚函数)
假设现在派生类继承基类,并且重新定义了3个虚函数(是派生类自己的虚函数),派生类会自己产生一个兼容基类虚函数表的属于自己的虚函数表。
Derive class 继承了 Base class 中的三个虚函数,准确的说,是该函数实体的地址被拷贝到 Derive类的虚函数表,派生类新增的虚函数置于虚函数表的后面,并按声明顺序存放。
· 单继承时的虚函数(重写基类虚函数)
现在派生类重写基类的x函数,可以看到这个派生类构建自己的虚函数表的时候,修改了base::x()这一项,指向了自己的虚函数。
· 多重继承时的虚函数(Derived ::public Base1,public Base2)
这个派生类多重继承了两个基类base1,base2,因此它有两个虚函数表。
它的对象会有多个虚指针(据说和编译器相关),指向不同的虚函数表。
多重继承时指针的调整:
Derive b;Base1* ptr1 = &b; // 指向 b 的初始地址Base2* ptr2 = &b; // 指向 b 的第二个子对象
因为 Base1 是第一个基类,所以 ptr1 指向的是 Derive 对象的起始地址,不需要调整指针(偏移)。
因为 Base2 是第二个基类,所以必须对指针进行调整,即加上一个 offset,让 ptr2 指向 Base2 子对象。
当然,上述过程是由编译器完成的。
Base1* b1 = (Base1*)ptr2;b1->y(); // 输出 Base2::y()Base2* b2 = (Base2*)ptr1;b2->y(); // 输出 Base1::y()
其实,通过某个类型的指针访问某个成员时,编译器只是根据类型的定义查找这个成员所在偏移量,用这个偏移量获取成员。
由于 ptr2 本来就指向 Base2 子对象的起始地址,所以b1->y()调用到的是Base2::y(),而 ptr1 本来就指向 Base1 子对象的起始地址(即 Derive对象的起始地址),所以b2->y()调用到的是Base1::y()。
- 虚函数表的问题
- 虚函数表合并的问题
- 虚函数表问题
- 虚函数表问题
- 函数的函数问题
- 函数的函数问题
- 关于虚函数的问题
- 虚函数的sizeof问题
- 虚函数的效率问题
- 虚函数 虚表问题
- C++ Daily 《5》----虚函数表的共享问题
- C++从虚函数表的底层来看虚函数调用问题
- 虚函数表 与 虚函数实现多态时应注意的问题
- 有关于虚函数的问题
- C++中虚函数的问题
- c#中虚函数的问题
- 证明下虚函数的调用问题
- 虚函数默认参数的问题记录
- 图文分享怎么画流程图的快捷技巧
- 【LEDE】树莓派上玩LEDE终极指南-94-在树莓派上搭建NextCloud私人云存储注意事项
- web权限管理
- 一些惊讶的语句 收集
- Ucos II 任务延时函数
- 虚函数表的问题
- TMS320C6678多核DSP的核间通信方法
- POJ 3790 最短路径问题(Dijkstra变形——最短路径双重最小权值)
- HA之DRBD详解(基于CentOS7.0)
- 【正则表达式1】C++11正则表达式
- ubuntu17.04下 selenium安装及使用
- gitlab新建项目过程和添加用户
- ABBYY FineReader 12中条码检测不到怎么办
- QT串口打印以及换行解决