为对象存储成员函数的位置在哪里?

Joh*_*ing 12 c++ memory function-pointers pointer-to-member

我正在尝试用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;
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:为什么这条线

unsigned int offset_from_start_structure = (unsigned int)(&((mystruct*)0)->c);
Run Code Online (Sandbox Code Playgroud)

编译并返回结构和行开头的"c"字段的偏移量

unsigned int offset_from_start_structure2 = (unsigned int)(&((mystruct*)0)->function);
Run Code Online (Sandbox Code Playgroud)

甚至不编译?

Luc*_*ore 17

成员函数或指向它们的指针不存储在对象中.(virtual函数通常通过存储在表中的指针来调用,对象具有单个指针)这将是对内存的巨大浪费.它们通常存储在代码存储器部分中,并且是编译器已知的.object(*this)通常作为不可见参数传递,因此函数知道调用它们时要操作的对象.

所以,通俗地说,你有

 0x10001000    void A::foo
 ..........    {code for A::foo}
Run Code Online (Sandbox Code Playgroud)

 push a;
 call A::foo (0x10001000)
 pop a;
Run Code Online (Sandbox Code Playgroud)

a你正在呼唤的对象在哪里foo.


Che*_*Alf 6

成员函数指针实际上不存储在对象中:没有必要。C++ 标准没有具体规定如何实现虚拟函数,但虚拟成员函数的常见做法是每个对象都包含一个指向函数指针表的指针;这个指针称为虚函数表指针

您可能会尝试获取Stanley Lippman 所著的《C++ 对象模型内部》

或者,您可能只是尝试获取我的旧指针教程,该教程曾经在维基百科的指针文章中引用过,然后我当时的主页网站消失了。


关于第二个问题,为什么获取 的地址p->memberFunc会让编译器有点窒息,那个表达式没有类型,它只是一个语法实体,您可以对其应用参数列表以调用该函数。

以机智,

struct S
{
    void foo() {}
};

#include <iostream>
#include <typeinfo>
using namespace std;
int main()
{
    S* p = 0;
    typeid( &p->foo );
} 
Run Code Online (Sandbox Code Playgroud)

汇编:

[W:\dev\测试]
> g++ foo.cpp
foo.cpp:在函数“int main()”中:
foo.cpp:12:17: 错误:ISO C++ 禁止使用绑定成员函数的地址来形成指向成员函数的指针。说“&S::foo”[-fpermissive]
foo.cpp:12:22:警告:未使用计算值 [-Wunused-value]
foo.cpp:12:22:警告:语句无效 [-Wunused-value]

[W:\dev\测试]
> _