我试图了解用于实现指向非静态成员函数的指针的底层机制。我正在寻找一个类似于 vtbl(多态虚拟表)如何在大局中工作的答案,而不用担心编译器之间可能会有所不同的细节。
例子:
#include <stdio.h>
class A {
public:
int i;
int j;
void foo(void) { };
};
int main ()
{
int A::*ptr_j = &A::j;
void (A::*ptr_f)(void) = &A::foo;
printf("Foo::j pointer to data member %p\r\n", ptr_j);
printf("Foo::foo pointer to function member %p\r\n", ptr_f);
}
结果是
Foo::j
指向数据成员的指针0x4
Foo::foo
指向函数成员的指针0x804844c
来自“Stroustrup 的 C++ 编程语言”,
指向成员的指针...更像是结构的偏移量或数组的索引...
对于数据成员,我知道 Pointer-To-MemberFoo::j
或多或少等同于offsetOf(Foo, j)
. 在我的主机环境中使用 gcc 编译器时的值是 4,它匹配的offsetOf(Foo, j)
是 4。
对于函数成员,返回值为0x804844c
. 这是属于全局数据区的一些地址(加载类的位置?)
所以我的问题是:
什么是 address 的“对象” 0x804844c
。
- 它不能是简单的
offsetOf()
,因为这是一个很大的偏移量。 - 它不能是 vtbl 的地址(或 vtbl 中条目的地址),因为我相信 vbtl 是与实例化对象相关联的实体,而不是与类相关联。
- 它不能是加载函数实现代码的地址。因为相同的指针在与派生对象一起应用时可以表现出多态性。
那么 address 处的对象是什么,当使用 operator or0x804844c
时,它在将指向成员函数的指针转换为实际函数地址中的作用是什么?->*
.*