我正在尝试使用C ++来理解类/结构及其各自的对象是如何在内存中布局的,我理解类/结构的每个字段都是它们各自对象的偏移(所以我可以有一个成员变量指针)。
我不明白为什么,即使我有成员函数指针,以下代码也不起作用:
struct mystruct
{
void function()
{
cout << "hello world";
}
int c;
};
int main()
{
unsigned int offset_from_start_structure = (unsigned int)(&((mystruct*)0)->c);
unsigned int offset_from_start_structure2 = (unsigned int)(&((mystruct*)0)->function); // ERROR - error C2276: '&' : illegal operation on bound member function expression
return 0;
}
我的问题是:为什么行
unsigned int offset_from_start_structure = (unsigned int)(&((mystruct*)0)->c);
编译并返回&#34; c&#34;的偏移量。从结构和行开始的字段
unsigned int offset_from_start_structure2 = (unsigned int)(&((mystruct*)0)->function);
甚至无法编译?
答案 0 :(得分:16)
成员函数或指向它们的指针不存储在对象中。 (virtual
函数通常通过存储在表中的指针来调用,对象只有一个指向的表。这将是巨大的内存浪费。它们通常存储在代码存储器部分中,并且编译器已知。对象(*this
)通常作为不可见参数传递,因此函数知道在调用它们时要操作的对象。
所以,通俗地说,你有
0x10001000 void A::foo
.......... {code for A::foo}
和
push a;
call A::foo (0x10001000)
pop a;
其中a
是您正在调用的对象foo
。
答案 1 :(得分:3)
成员函数指针实际上不存储在对象中:没有必要。 C ++标准没有具体说明如何虚函数是要实现的,但虚函数成员函数的常用做法是每个对象都包含一个指向函数指针表的指针;此指针称为 vtable pointer 。
您可能会尝试抓住Stanley Lippman的 “Inside the C++ object model” 。
或者,你可能只是试着抓住我的旧的 pointers tutorial ,这个曾经从维基百科的指针文章中引用,然后我的主页网站就消失了。
关于第二个问题,为什么取p->memberFunc
的地址会使编译器窒息,表达式没有类型,它只是一个语法实体,你可以应用它参数列表为了调用函数。
即便,
struct S
{
void foo() {}
};
#include <iostream>
#include <typeinfo>
using namespace std;
int main()
{
S* p = 0;
typeid( &p->foo );
}
汇编:
[W:\dev\test] > g++ foo.cpp foo.cpp: In function 'int main()': foo.cpp:12:17: error: ISO C++ forbids taking the address of a bound member function to form a pointer to member function. Say '&S::foo' [-fpermissive] foo.cpp:12:22: warning: value computed is not used [-Wunused-value] foo.cpp:12:22: warning: statement has no effect [-Wunused-value] [W:\dev\test] > _