首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

种成员函数指针的大小不是4?

2013-01-07 
类成员函数指针的大小不是4??32位平台typedef void (B::*PFUN)()PFUN* pFuncList *((PFUN**)pb)// pb

类成员函数指针的大小不是4??
32位平台


        typedef void (B::*PFUN)();
        PFUN* pFuncList = *((PFUN**)pb);  // pb是对象首地址
PFUN p1Func = pFuncList[0];
PFUN p2Func = pFuncList[1];//错误 总是偏移8 调用错误
p2Func = *(PFUN*)((char*)pFuncList + 4);//这个可以

__asm
{
mov ecx,pb;
call [p1Func];//  无参

mov ecx,pb;
push 333;
call [p2Func];//   一个参数
}

[解决办法]
这么神奇会偏移8?
我这边无论是目测还是机测都是ok的。
用下面这个会怎样?

PFUN p2Func = *(PFUN*)((int*)pFuncList + 1);

[解决办法]
《深度探索C++对象模型》
[解决办法]
引用:
《深度探索C++对象模型》


-__-!,赵老师,您老赋值粘贴可不好
很明显楼主熟习内存布局,成员函数调用也都注意了this的传递,代码本身也没有错。
只可能和楼主的编译运行环境有关系。
[解决办法]
引用:
《深度探索C++对象模型》



一般人不适合看这本书.
这本书是基于特殊的编译器的.它说的只是C++ 的众多实现中的一个或几个.
很多人误以为是C++ 规定要这么实现的.比如楼主.
[解决办法]
不一定是4 
印象中BCB下是9 
[解决办法]
【个人意见】8字节没有错啊
[解决办法]
要分 有虚表和 无虚表的情况
[解决办法]
4个字节包含的信息在多继承时是不够用的,
对于派生类的类成员函数指针,可能指向任意一个基类的成员函数,
当指向基类的成员函数时,这个成员函数隐含的第一个参数是该基类的this指针,而调用点上一般是派生类的对象或派生类的指针,所以在调用指向基类的成员函数时必须对this指针进行调整。
[解决办法]
从4到20都可能。本来C++标准就没规定它的大小。
你也根本不该依赖它有多大。
[解决办法]
函数的的参数,隐含的第一个参数貌似都是this,就是地址。
[解决办法]
引用:
引用:

《深度探索C++对象模型》


-__-!,赵老师,您老赋值粘贴可不好
很明显楼主熟习内存布局,成员函数调用也都注意了this的传递,代码本身也没有错。
只可能和楼主的编译运行环境有关系。


承认!!
连内联汇编都来了。。。

不过 成员函数调用也都注意了this的传递 ,没有看出来啊。??
[解决办法]
这代码是病毒吗?吓住我了。
写了这个代码,放在vs,本来想看看运行结果,结果vs关了,程序关不了,!!!任务管理器杀不死,关机关不了,杀毒软件启不动,命令行呼不出。

一个访问虚表的程序做了什么?
还有 push 333干神马??
[解决办法]
引用:
从4到20都可能。本来C++标准就没规定它的大小。
你也根本不该依赖它有多大。
的确如此,不同的编译器,不同的类型,指向其成员的指针大小也可能是不同的.
指向成员的指针其实是一个小型的对象,并不是一个简单的地址.对于32位程序,我一般假设32字节大小是够用的(有时为了保险也用48或64).对于多数情况来说,好像这样假设是没有问题的.但没有测试过拥有特别复杂继承体系的类型.随着继承体系的复杂化,这个"指针"的大小是有可能变化的.
[解决办法]
好奇怪的事情
[解决办法]
微软的编译器也不只有一个, 
还是在瞎猜不该猜的东西..
[解决办法]
引用:

这代码是病毒吗?吓住我了。
写了这个代码,放在vs,本来想看看运行结果,结果vs关了,程序关不了,!!!任务管理器杀不死,关机关不了,杀毒软件启不动,命令行呼不出。

一个访问虚表的程序做了什么?
还有 push 333干神马??


你那个是微软补丁的僵尸窗口问题吧
[解决办法]
Inside C++ 貌似说过,不同编译器对象的内存布局是有差别的,有的vtbl在基址最前,有的则放在后边。
[解决办法]
VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
指针即地址。“地址又是啥?”“只能从汇编语言和计算机组成原理的角度去解释了。”

提醒:
“学习用汇编语言写程序”

“VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
想要从本质上理解C指针,必须学习C和汇编的对应关系。”
不是一回事!

不要迷信书、考题、老师、回帖;
要迷信CPU、编译器、调试器、运行结果。
并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。
任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实!

不要写连自己也预测不了结果的代码!

[解决办法]
是滴
32为
[解决办法]
引用:
直接sizeof(PFUN)就是8了 微软的c++编译器 汗


纳尼?不可能!难道是?楼主你不该会是犯了类似下面这样的低级错误吧

#include "stdafx.h"
#include <iostream>
using namespace std;


class Base1
{
public:
   void funA() { }
};


class Base2
{
public:
    void funB() { }
};


class B : public Base1, public Base2
{
public:
    virtual void funD1() {cout<<1<<endl;}
    virtual void funD2(int var) {cout<<var<<endl;}
};


int main()
{
typedef void (B::*PFUN)();
int nPFUNLength = sizeof(PFUN);//这个就是8

B* pb = new B();
PFUN* pFuncList = *((PFUN**)pb);  // pb是对象首地址
PFUN p1Func = pFuncList[0];
PFUN p2Func = pFuncList[1];    //    错误 总是偏移8 调用错误
p2Func = *(PFUN*)((char*)pFuncList + 4);    //    这个可以

__asm
{
mov ecx,pb;
call [p1Func];//  无参

mov ecx,pb;
push 333;
call [p2Func];//   一个参数
}

getchar();
        return 0;

}

热点排行