虚函数杂记
2015-09-15 00:22
239 查看
在之前的一篇博文C++中的虚函数表是什么时期建立的?,我们知道虚函数表在编译期间就生成了,但是它被放置在可执行文件的什么地方呢?
在C++对象模型中,nonstatic data members被配置于每一个class object中,static data members则被存放在个别的class object之外。static和nonstatic function members也被放在个别的class object之外。virtual functions则以两个步骤支持之:
1. 每一个class产生出一堆指向virtual functions的指针,放在表格之中。这个表格被称为virtual table (vtbl)。
2. 每一个class object被安插一个指针,指向相关的virtual table。通常这个指针被称为vptr。vptr的设定(setting)和重置(resetting)都由每一个class的constructor、destructor和copy assignment运算符自动完成。每一个class所关联的type_info object(用以支持runtime type identification, RTTI)也经由virtual talbe被指出来,通常放在表格的第一个slot。
我们以一个程序来说明C++对象模型:
其对应的对象模型为:
View Code
虚函数表放置位置
为了解决这个问题,我们先来看下C++对象模型。在C++对象模型中,nonstatic data members被配置于每一个class object中,static data members则被存放在个别的class object之外。static和nonstatic function members也被放在个别的class object之外。virtual functions则以两个步骤支持之:
1. 每一个class产生出一堆指向virtual functions的指针,放在表格之中。这个表格被称为virtual table (vtbl)。
2. 每一个class object被安插一个指针,指向相关的virtual table。通常这个指针被称为vptr。vptr的设定(setting)和重置(resetting)都由每一个class的constructor、destructor和copy assignment运算符自动完成。每一个class所关联的type_info object(用以支持runtime type identification, RTTI)也经由virtual talbe被指出来,通常放在表格的第一个slot。
我们以一个程序来说明C++对象模型:
class Point { public: Point(float xval); virtual ~Point(); float x() const; static int PointCount(); protected: virtual ostream& print(ostream &os) const; float x; static int _point_count; }
其对应的对象模型为:
#include <iostream> using namespace std; class Base1 { public: virtual void f() { cout << "Base1::f" << endl; } virtual void g() { cout << "Base1::g" << endl; } virtual void h() { cout << "Base1::h" << endl; } }; class Base2 { public: virtual void f() { cout << "Base2::f" << endl; } virtual void g() { cout << "Base2::g" << endl; } virtual void h() { cout << "Base2::h" << endl; } }; class Base3 { public: virtual void f() { cout << "Base3::f" << endl; } virtual void g() { cout << "Base3::g" << endl; } virtual void h() { cout << "Base3::h" << endl; } }; class Derive : public Base1, public Base2, public Base3 { public: virtual void f() { cout << "Derive::f" << endl; } virtual void g1() { cout << "Derive::g1" << endl; } }; typedef void(*Fun)(void); int main() { Fun pFun = NULL; Derive d; int** pVtab = (int**)&d; //Base1's vtable //pFun = (Fun)*((int*)*(int*)((int*)&d+0)+0); pFun = (Fun)pVtab[0][0]; pFun(); //pFun = (Fun)*((int*)*(int*)((int*)&d+0)+1); pFun = (Fun)pVtab[0][1]; pFun(); //pFun = (Fun)*((int*)*(int*)((int*)&d+0)+2); pFun = (Fun)pVtab[0][2]; pFun(); //Derive's vtable //pFun = (Fun)*((int*)*(int*)((int*)&d+0)+3); pFun = (Fun)pVtab[0][3]; pFun(); //The tail of the vtable pFun = (Fun)pVtab[0][4]; cout << pFun << endl; //Base2's vtable //pFun = (Fun)*((int*)*(int*)((int*)&d+1)+0); pFun = (Fun)pVtab[1][0]; pFun(); //pFun = (Fun)*((int*)*(int*)((int*)&d+1)+1); pFun = (Fun)pVtab[1][1]; pFun(); pFun = (Fun)pVtab[1][2]; pFun(); //The tail of the vtable pFun = (Fun)pVtab[1][3]; cout << pFun << endl; //Base3's vtable //pFun = (Fun)*((int*)*(int*)((int*)&d+1)+0); pFun = (Fun)pVtab[2][0]; pFun(); //pFun = (Fun)*((int*)*(int*)((int*)&d+1)+1); pFun = (Fun)pVtab[2][1]; pFun(); pFun = (Fun)pVtab[2][2]; pFun(); //The tail of the vtable pFun = (Fun)pVtab[2][3]; cout << pFun << endl; return 0; }
View Code
参考资料
《深入探索C++对象模型》相关文章推荐
- LeetCode Sqrt(x)
- 《我与大数据的365天》 ——(3) 【写代码观察数据变化】
- LeetCode Sqrt(x)
- AndroidStudio安装
- 设计模式学习笔记二十四:优雅的菜单 - 组合模式
- C# “快捷方式” 实现程序开机启动
- [LeetCode][JavaScript]Binary Tree Inorder Traversal
- android点滴记录1
- java 发送HTTPS请求
- oracle 用Navicat创建的表的查询问题
- Unity3D逆向基础教程第五课
- 抽象工厂模式【转载】
- 基本Socket通信流程
- 神器VS2010:c/c++ &&&&&& masm->obj link编译与连接
- java点滴记录1
- shell简介及变量、脚本相关概念
- linux 安装jdk及tomcat指定jdk版本
- 信息检索学习笔记
- Unity3D逆向基础教程第四课
- 美版Linksys WRT1900AC v1刷OpenWrt经验