vptr的初始化
来源:互联网 发布:减脂练马甲线软件 编辑:程序博客网 时间:2024/05/18 05:39
class base
{
int i;
public:
base(int I):i(I){}
virtual int sum(){return i;}
};
主程序
base b(100);
b.sum();
看base的构造函数
class base
{
int i;
public:
base(int I):i(I){}
00401250 push ebp
00401251 mov ebp,esp
00401253 push ecx
00401254 mov dword ptr [ebp-4],ecx
00401257 mov eax,dword ptr [this]
0040125A mov dword ptr [eax],offset base::`vftable' (402164h) //对象首地址写入offset vftable
00401260 mov ecx,dword ptr [this]
00401263 mov edx,dword ptr [I] //i 写入edx
00401266 mov dword ptr [ecx+4],edx //edx写入首地址+4
00401269 mov eax,dword ptr [this] //返回this
0040126C mov esp,ebp
0040126E pop ebp
0040126F ret 4
我们看到内存 402164放着401280
virtual int sum(){return i;}
00401280 push ebp
00401281 mov ebp,esp
00401283 push ecx
00401284 mov dword ptr [ebp-4],ecx
00401287 mov eax,dword ptr [this]
0040128A mov eax,dword ptr [eax+4]
0040128D mov esp,ebp
0040128F pop ebp
00401290 ret
现在有了个小结论:
vptr的初始化在构造函数内,由编译器悄悄生成, 成员初始化之前,问题来了 如果在构造函数内调用未被初始化的成员,会发生什么?
什么都没发生,一切正常
class base
{
int i;
public:
base(int I):i(I){add();}
00401250 push ebp
00401251 mov ebp,esp
00401253 push ecx
00401254 mov dword ptr [ebp-4],ecx
00401257 mov eax,dword ptr [this]
0040125A mov dword ptr [eax],offset base::`vftable' (402164h)
00401260 mov ecx,dword ptr [this]
00401263 mov edx,dword ptr [I]
00401266 mov dword ptr [ecx+4],edx
00401269 mov ecx,dword ptr [this]
0040126C call base::add (4012A0h) //不论是不是虚函数,都在成员初始化之后
00401271 mov eax,dword ptr [this]
00401274 mov esp,ebp
00401276 pop ebp
00401277 ret 4
不清楚各个编译器的是不是不同,这是我在vc2005下的结果
再看派生类的,从汇编可以看出,是用派生类的vptr 代替了base的vptr
base(int I):i(I){printf("base vptr=%x",*(int*)this);}
derived(int I,int J):base(I),j(J) {printf("derived vptr=%x",*(int*)this);}
在构造函数里直接输出了vptr
base(int I):i(I){printf("base vptr=%x",*(int*)this);}
00401260 push ebp
00401261 mov ebp,esp
00401263 push ecx
00401264 mov dword ptr [ebp-4],ecx
00401267 mov eax,dword ptr [this]
0040126A mov dword ptr [eax],offset base::`vftable' (402174h)
00401270 mov ecx,dword ptr [this]
00401273 mov edx,dword ptr [I]
00401276 mov dword ptr [ecx+4],edx
00401279 mov eax,dword ptr [this]
0040127C mov ecx,dword ptr [eax]
0040127E push ecx
0040127F push offset string "base vptr=%x" (402160h)
00401284 call dword ptr [__imp__printf (4020ACh)]
0040128A add esp,8
0040128D mov eax,dword ptr [this]
00401290 mov esp,ebp
00401292 pop ebp
00401293 ret 4
class derived:public base
{
int j;
public:
derived(int I,int J):base(I),j(J) {printf("derived vptr=%x",*(int*)this);}
004012C0 push ebp
004012C1 mov ebp,esp
004012C3 push ecx
004012C4 mov dword ptr [ebp-4],ecx
004012C7 mov eax,dword ptr [I]
004012CA push eax
004012CB mov ecx,dword ptr [this]
004012CE call base::base (401260h)
004012D3 mov ecx,dword ptr [this]
004012D6 mov dword ptr [ecx],offset derived::`vftable' (40218Ch)
004012DC mov edx,dword ptr [this]
004012DF mov eax,dword ptr [J]
004012E2 mov dword ptr [edx+8],eax
004012E5 mov ecx,dword ptr [this]
004012E8 mov edx,dword ptr [ecx]
004012EA push edx
004012EB push offset string "derived vptr=%x" (402178h)
004012F0 call dword ptr [__imp__printf (4020ACh)]
004012F6 add esp,8
004012F9 mov eax,dword ptr [this]
004012FC mov esp,ebp
004012FE pop ebp
004012FF ret 8
主程序
base b(100);
derived d(200,400);
结果输出了3个
base vptr=402174 base vptr=402174 derived vptr=40218c
是不是跟你想的一样?
- vptr的初始化
- vptr的初始化语义学
- C++vptr初始化时间
- vptr初始化语义学
- 子类的vptr指针是分步初始化的_多态相关面试
- 关于vptr的一些问题
- 证明vptr指针的存在
- 深度探索c++对象模型之vptr初始化语意学
- vptr被设置内容的时机
- C++中vptr指针的存在
- C/C++—— 在构造函数中调用虚函数能实现多态吗(Vptr指针初始化的过程分析)
- C++ vtable的生成以及vptr的赋值跟踪实验
- C++ vtable的生成以及vptr的赋值跟踪实验
- 重温《C++ Primer》笔记七 VTABLE与VPTR的实现
- 多态原理探究_证明vptr指针的存在
- vptr指针
- C++中空类的大小和类的虚表指针(vptr)
- 深入理解C++对象模型-对象的内存布局,vptr,vtable
- 目瞪口呆!台湾豪门美女过如此奢华生活?
- windowsxp登陆过程
- 设计模式原则
- 在axis中通过wsdd文件发布和卸载webservice
- 贴判断多个邮箱地址的代码
- vptr的初始化
- 关羽在韩国有块私家地?
- C#转义符
- CBasePin类、CBaseOutputPin类和CBaseInputPin类源代码解析(1)(转贴)
- CBasePin类、CBaseOutputPin类和CBaseInputPin类源代码解析(2)(转贴)
- SaaS模式和ASP模式
- C的优先级口诀
- 上海最帅交警迷倒一片女白领成为城市风景
- 关于java和jar命令的几点心得