虚函数表
来源:互联网 发布:淘宝淘词助手官网 编辑:程序博客网 时间:2024/06/07 20:54
原文地址 http://yoyo.is-programmer.com/posts/10671.html
检测方法(VS2005):项目命令行加上参数/d1reportAllClassLayout,在编译时CTRL+F5搜索输出,查看类的对象布局。
vftable - 虚函数表; vbtable - 虚继承的父类表; member - 类的成员变量(这个只是写作方便说明 = =)。
总结:
- 继承方式:非virtual继承:导入各个父类的结构(按照父类声明的顺序,从上到下),自身member在最后
- 重写virtual方法:更新该方法最早定义的类的vftable
- 新的virtual方法:在最左父类的vftable增加
- 继承方式:有virtual继承:在自身member后增加virtual父类的结构(按照子类继承的顺序从左到右),同时在最前面增加vbtable(如果没有的话),增加一项指向父类结构
- 重写virtual方法:更新该方法的最早定义的类的vftable
- 新的virtual方法:在自身最前面增加vftable(如果没有的话),在自己的vftable增加
测试代码(非常乱):
CBase:持有一个virtual方法和一个成员变量,因此结构只有{vftable}和member,其中{vftable}只有一项:CBase::fun()。
class CBase
{
public:
virtual void fun(void) { }
public:
int base;
};
1>class CBase size(8):
1> +---
1> 0 | {vfptr}
1> 4 | base
1> +---
1>CBase::$vftable@:
1> | &CBase_meta
1> | 0
1> 0 | &CBase::fun
1>CBase::fun this adjustor: 0
CDerived:非virtual继承CBase,持有一个virtual重写方法和一个virtual新方法,一个成员变量,因此结构为 CBase结构(vftable@CBase, member@CBase),以及自身member。其中vftable@CBase的CBase::fun项在这里更新为CDerived::fun,同时增加了一项CDerived::vfun。
class CDerived: public CBase
{
public:
void fun(void) { }
virtual void vfun(void) { }
public:
int derived;
};
1>class CDerived size(12):
1> +---
1> | +--- (base class CBase)
1> 0 | | {vfptr}
1> 4 | | base
1> | +---
1> 8 | derived
1> +---
1>CDerived::$vftable@:
1> | &CDerived_meta
1> | 0
1> 0 | &CDerived::fun
1> 1 | &CDerived::vfun
1>CDerived::fun this adjustor: 0
1>CDerived::vfun this adjustor: 0
CDerived2:virtual继承CBase,持有一个virtual重写方法和一个virtual新方法,一个成员变量,因此结构为vftable@自身,vbtable@自身,member@自身,以及CBase结构。其中vftable@自身只有一项:CDerived2::vfun(),vbtable@自身只有一项:它virtual继承的父类CBase,而vftable@CBase原来的CBase::fun更新为CDerived2::fun。
{
public:
void fun(void) { }
virtual void vfun(void) { }
public:
int derived2;
};
1>class CDerived2 size(20):
1> +---
1> 0 | {vfptr}
1> 4 | {vbptr}
1> 8 | derived2
1> +---
1> +--- (virtual base CBase)
1>12 | {vfptr}
1>16 | base
1> +---
1>CDerived2::$vftable@CDerived2@:
1> | &CDerived2_meta
1> | 0
1> 0 | &CDerived2::vfun
1>CDerived2::$vbtable@:
1> 0 | -4
1> 1 | 8 (CDerived2d(CDerived2+4)CBase)
1>CDerived2::$vftable@CBase@:
1> | -12
1> 0 | &CDerived2::fun
1>CDerived2::fun this adjustor: 12
1>CDerived2::vfun this adjustor: 0
1>vbi: class offset o.vbptr o.vbte fVtorDisp
1> CBase 12 4 4 0
CDerived3:virtual继承CBase,因此结构为vbtable@自身,member@自身,CBase结构。vbtable@自身只有一项指向CBase结构。
{
public:
void fun(void) { }
public:
int derived3;
};
1> +---
1> 0 | {vbptr}
1> 4 | derived3
1> +---
1> +--- (virtual base CBase)
1> 8 | {vfptr}
1>12 | base
1> +---
1>CDerived3::$vbtable@:
1> 0 | 0
1> 1 | 8 (CDerived3d(CDerived3+0)CBase)
1>CDerived3::$vftable@:
1> | -8
1> 0 | &CDerived3::fun
1>CDerived3::fun this adjustor: 8
1>vbi: class offset o.vbptr o.vbte fVtorDisp
1> CBase 8 0 4 0
CGDerived:继承CDerived2、CDerived3,因此首先是CDerived2的结构和CDerived3的结构,自己的新virtual方法vgfun则添加在最左父类CDerived2的虚函数表中。然后是自己的成员。最后,CDerived2和CDerived3的父类CBase结构也带入其中。它的fun默认指向CGDerived的最左父类CDerived2::fun。
{
public:
void vfun() { }
virtual void vgfun() { }
public:
int gd;
};
1> +---
1> | +--- (base class CDerived2)
1> 0 | | {vfptr}
1> 4 | | {vbptr}
1> 8 | | derived2
1> | +---
1> | +--- (base class CDerived3)
1>12 | | {vbptr}
1>16 | | derived3
1> | +---
1>20 | gd
1> +---
1> +--- (virtual base CBase)
1>24 | {vfptr}
1>28 | base
1> +---
1>CGDerived::$vftable@CDerived2@:
1> | &CGDerived_meta
1> | 0
1> 0 | &CGDerived::vfun
1> 1 | &CGDerived::vgfun
1>CGDerived::$vbtable@CDerived2@:
1> 0 | -4
1> 1 | 20 (CGDerivedd(CDerived2+4)CBase)
1>CGDerived::$vbtable@CDerived3@:
1> 0 | 0
1> 1 | 12 (CGDerivedd(CDerived3+0)CBase)
1>CGDerived::$vftable@CBase@:
1> | -24
1> 0 | &thunk: this-=12; goto CDerived2::fun
1>CGDerived::vfun this adjustor: 0
1>CGDerived::vgfun this adjustor: 0
1>vbi: class offset o.vbptr o.vbte fVtorDisp
1> CBase 24 4 4 0
CGG:继承CGDerived,增加一个变量,基本只是把CGDerived的结构再套一层,最后加上自己的成员变量。vbtable所指向的父类结构依然在最后。
class CGG: public CGDerived
{
public:
int kc;
};
1>class CGG size(36):
1> +---
1> | +--- (base class CGDerived)
1> | | +--- (base class CDerived2)
1> 0 | | | {vfptr}
1> 4 | | | {vbptr}
1> 8 | | | derived2
1> | | +---
1> | | +--- (base class CDerived3)
1>12 | | | {vbptr}
1>16 | | | derived3
1> | | +---
1>20 | | gd
1> | +---
1>24 | kc
1> +---
1> +--- (virtual base CBase)
1>28 | {vfptr}
1>32 | base
1> +---
1>CGG::$vftable@CDerived2@:
1> | &CGG_meta
1> | 0
1> 0 | &CGDerived::vfun
1> 1 | &CGDerived::vgfun
1>CGG::$vbtable@CDerived2@:
1> 0 | -4
1> 1 | 24 (CGGd(CDerived2+4)CBase)
1>CGG::$vbtable@CDerived3@:
1> 0 | 0
1> 1 | 16 (CGGd(CDerived3+0)CBase)
1>CGG::$vftable@CBase@:
1> | -28
1> 0 | &thunk: this-=16; goto CDerived2::fun
1>vbi: class offset o.vbptr o.vbte fVtorDisp
1> CBase 28 4 4 0
CBase2:空类默认都有一个占位,size为1
{
};
1> +---
1> +---
CD2:virtual继承则一定会创建vbtable,用vbptr指针指向,因此size为4。
{
};
1> +---
1> 0 | {vbptr}
1> +---
1> +--- (virtual base CBase2)
1> +---
1>CD2::$vbtable@:
1> 0 | 0
1> 1 | 4 (CD2d(CD2+0)CBase2)
1>vbi: class offset o.vbptr o.vbte fVtorDisp
1> CBase2 4 0 4 0
CE:非virtual继承CD2和CDerived2,于是按照类的声明顺序,先带入CDerived2的结构,再带入CD2的结构(而不是按继承顺序)。
{
};
1> +---
1> | +--- (base class CDerived2)
1> 0 | | {vfptr}
1> 4 | | {vbptr}
1> 8 | | derived2
1> | +---
1> | +--- (base class CD2)
1>12 | | {vbptr}
1> | +---
1> +---
1> +--- (virtual base CBase2)
1> +---
1> +--- (virtual base CBase)
1>16 | {vfptr}
1>20 | base
1> +---
1>CE::$vftable@CDerived2@:
1> | &CE_meta
1> | 0
1> 0 | &CDerived2::vfun
1>CE::$vbtable@CD2@:
1> 0 | 0
1> 1 | 4 (CEd(CD2+0)CBase2)
1> 2 | 4 (CEd(CE+12)CBase)
1>CE::$vbtable@CDerived2@:
1> 0 | -4
1> 1 | 12 (CEd(CDerived2+4)CBase)
1>CE::$vftable@CBase@:
1> | -16
1> 0 | &thunk: this-=4; goto CDerived2::fun
1>vbi: class offset o.vbptr o.vbte fVtorDisp
1> CBase2 16 12 4 0
1> CBase 16 12 8 0
CF:virtual继承CBase和CBase2,vbtable此时的项便有两个,此时按照继承的顺序,而不是按照类的声明顺序。
{
};
1> +---
1> 0 | {vbptr}
1> +---
1> +--- (virtual base CBase2)
1> +---
1> +--- (virtual base CBase)
1> 4 | {vfptr}
1> 8 | base
1> +---
1>CF::$vbtable@:
1> 0 | 0
1> 1 | 4 (CFd(CF+0)CBase2)
1> 2 | 4 (CFd(CF+0)CBase)
1>CF::$vftable@:
1> | -4
1> 0 | &CBase::fun
1>vbi: class offset o.vbptr o.vbte fVtorDisp
1> CBase2 4 0 4 0
1> CBase 4 0 8 0
- 虚函数,虚析构函数,虚函数表
- 虚函数 虚函数表
- 虚函数表 构造函数
- 虚函数和纯虚函数及虚函数表
- 子类虚函数表(包括虚函数+函数)
- 虚函数、虚函数表、虚继承
- 通过函数指针使用虚函数表中的函数
- 虚函数表指针,虚函数表
- 虚函数表指针,虚函数表
- 关于 [虚函数] 和 [虚函数表]
- C++虚函数与虚函数表
- C++虚函数与虚函数表
- 虚函数与虚函数表
- c++ 虚函数和虚函数表
- c++虚函数和虚函数表
- [收集]虚函数及虚函数表
- C++ 虚函数,虚函数表
- C++虚函数与虚函数表
- 继承类要实现接口父类的所有方法吗
- 微信小程序 the server responded with a status of 404 错误解决方法
- Div#432B Arpa and an exam about geometry
- 怎么学 JavaScript?
- OpenCV编程->USB摄像头参数调试
- 虚函数表
- cxf生成webservice的java客户端代码
- 长按水波纹,拖拽取消发送的语音控件
- socket编程---send函数&recv函数详解
- Gradle插件之判断环境环境变量
- 某安全浏览器竟然也被查出高危漏洞?开源安全问题不容忽视
- Linux实验—搭建路由环境
- Android常用开源框架
- 思维会骗人,程序不骗人。