C++对象模型的演变及验证 (1)
来源:互联网 发布:淘宝店铺模板源代码 编辑:程序博客网 时间:2024/06/05 13:22
2012-11-10 wcdj
关键字:C++对象模型, 访问私有成员, 虚函数, 虚函数表(vtbl), 虚函数表指针(vptr), 类成员函数指针
C++对象模型的演变
在C++中:
有两种类数据成员:(1) static (2) nonstatic
有三种类成员函数:(1) static (2) nonstatic (3)virtual
C++对象模型的演变过程:
(1) 简单对象模型
一个object是一系列的slots,每个slot指向一个members。在这个简单模型中,members本身并不放在object之中,只有指向member的指针才放在object内。
此模型提出了一种思想:使用索引的思想,之后被应用到C++的指向成员的指针思想中。
(2) 表格驱动模型
class object本身则内含指向这两个表格的指针,一个指向data member table,一个指向member function table。其中,member function table是一系列的slots,每一个slot指出一个member function;而data member table则直接含有data本身。
此模型也提出了一种思想:member function table的思想成为以后virtual functions的一个有效解决方案。
(3) C++对象模型
nonstatic data members被置于每一个class object之内,static data members则被存放在所有的class object之外,并且,static和nonstatic function members也被放在所有的class object之外。
virtual functions则以两个步骤支持之:
[1] 存在一个virtual table。每一个class产生一堆指向virtual functions的指针,并存放在这张表中。(根据虚函数声明的顺序存放)
[2] 每一个class object被添加了一个指针,指向相关的virtual table。(这个指针被称为vptr)
注意:
(a) vptr的设定和重置都有每一个class的constructor、destructor和copy assignment运算符自动完成。
(b) 每一个class所关联的type_info object (用以支持runtime type identification, RTTI)也经由virtua ltable 被指出来, 通常是放在表格的第一个slot处。(注意实践表明可能不是这样)
C++对象模型简单case验证
了解了C++对象模型之后,可以对其进行简单的验证,不同的编译器可能实现有所不同。下面的例子考虑最简单的情况,暂时不考虑继承,主要测试以下几点:
环境:Windows Server 2003, 32位 + VS2008
(1) 根据对象模型计算类成员偏移量, 并通过偏移量来访问类成员,包括类的私有成员;
(2) 定义类成员函数指针, 并通过类成员函数指针访问类成员函数;
/* 2012-11-10 wcdj * C++虚函数表的实例解析 */#include <stdio.h>// 指定按1字节对齐#pragma pack(1)// 定义普通函数指针typedef void(*Fun)(void);// 定义类成员函数指针class Base;typedef void(Base::*CFun)(void);#define callMemFun(obj, pCFun) ( (obj).*(pCFun) )#define pcallMemFun(pobj, pCFun) ( (pobj)->*(pCFun) ) class Base{public:// constructor and destructorBase() {}Base(int a, char b): m_iA(a), m_cB(b) {}virtual ~Base() {}// virtual functionsvirtual void f(){ printf("invork f()\n"); }virtual void g(){ printf("invork g()\n"); }virtual void h(){ printf("invork h()\n"); }// non-virtual functionsvoid test(){ printf("This is non-virtual function named test\n"); }void test2(){ printf("This is non-virtual function named test2\n"); }private:int m_iA;char m_cB;};int main(){Base a, b(1, 'x');// 计算类的大小// sizeof(Base) = sizeof(vfptr) + sizeof(m_iA) + sizeof(m_cB) = 4 + 4 + 1 printf("the size of Base: %d\n", sizeof(a));printf("the size of Base: %d\n", sizeof(b));/* [1] 计算类成员偏移量, 并通过偏移量来访问类成员, 包括类的私有成员 */Fun pFun = NULL;// 对象实例地址printf("&b = 0x%x\n", &b);// 虚函数表地址/* 可以发现, 虚函数表的指针存在于对象实例中最前面的位置 * 说明: * 在Inside The C++ Object Model中有注释说, 每一个class所关联的 * type_info object (用以支持runtime type identification, RTTI)也经由 * virtual table 被指出来, 通常是放在表格的第一个slot处*/printf("*(int *)(&b) = 0x%x\n", *(int *)(&b));// 虚函数表中第一个虚函数的地址printf("*(int*)(*(int *)(&b)) = 0x%x\n", *(int*)(*(int *)(&b)));// 通过偏移量来分别获取类的成员// 注意: 虚函数按照其声明的顺序置于虚函数表中// 需要强制转换为函数指针 // Base的destructor函数, 此时不能调用pFun = (Fun)*((int *)*(int *)(&b) + 0);//pFun();// f()pFun = (Fun)*((int *)*(int *)(&b) + 1);pFun();// g()pFun = (Fun)*((int *)*(int *)(&b) + 2);pFun();// h()pFun = (Fun)*((int *)*(int *)(&b) + 3);pFun();// m_iAint iA = *((int *)(&b) + 1);printf("iA=%d\n", iA);// 1// m_cBchar cB = *(char *)((int *)(&b) + 2);printf("cB=%c\n", cB);// x// 注意: 普通成员函数属于类的级别而不属于对象级别b.test();printf("&Base::test = 0x%x\n", &Base::test);printf("&Base::test2 = 0x%x\n", &Base::test2);/* [2] 定义类成员函数指针, 并通过类成员函数指针访问类成员函数 */// 注意区别类成员函数指针和普通函数指针定义的方法CFun pCFun = NULL;// [1]pCFun = &Base::test;((b).*(pCFun))();// [2]pCFun = &Base::f;callMemFun(b, pCFun)();// [3]pCFun = &Base::g;pcallMemFun(&b, pCFun)();// [4]pCFun = &Base::test;pcallMemFun(&b, pCFun)();return 0;}/*output:the size of Base: 9the size of Base: 9&b = 0x12ff3c*(int *)(&b) = 0x60f3e8*(int*)(*(int *)(&b)) = 0x4b0701invork f()invork g()invork h()iA=1cB=xThis is non-virtual function named test&Base::test = 0x4aedca&Base::test2 = 0x4b263cThis is non-virtual function named testinvork f()invork g()This is non-virtual function named test*/
参考:
[1] C++ 虚函数表解析
[2] 类的普通成员函数的指针
[3] 深度探索C++对象模型,Inside The C++ Object Model
- C++对象模型的演变及验证 (1)
- C++对象模型的演变及验证 (2)
- Reactor模型的演变
- 生产者消费者模型的演变
- c语言的演变
- Objective-C对象模型及应用
- Objective-C对象模型及应用
- Objective-C对象模型及应用
- Objective-C对象模型及应用
- Objective-C对象模型及应用
- Objective-C对象模型及应用
- Objective-C对象模型及应用
- Objective-C对象模型及应用
- Objective-C对象模型及应用
- Objective-C对象模型及应用
- Objective-C对象模型及应用
- Objective-C对象模型及应用
- C/C++的对象模型
- 中国国旗图片生成代码-jsp版本
- 如何根据一个数组建立最大堆
- 敏捷软件开发宣言及敏捷宣言遵循的原则
- C++复制控制之复制构造函数(一)
- 补充,加水印程序有一个文件过滤器,可以选择指定的图片文件
- C++对象模型的演变及验证 (1)
- SAP HANA SQL 精萃
- C#程序设计(二十一)----编写一个图片不断向左移动的小动画
- C/C++返回内部静态成员的陷阱
- HDU2612 (Find a way)
- 语义网学习笔记(1) XML
- Science G-1 101 - Colors, Shapes, Sizes
- flex treegrid编辑操作
- main()函数返回值的分析