【发布时间】:2013-07-24 21:07:45
【问题描述】:
我试图了解用于实现指向非静态成员函数的指针的底层机制。我正在寻找一个类似于 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-Member Foo::j 或多或少等同于 offsetOf(Foo, j)。在我的宿主环境中使用 gcc 编译器时的值为 4,与 offsetOf(Foo, j) 为 4 匹配。
对于函数成员,返回值为0x804844c。这是属于全局数据区的某个地址(加载类的地方?)
所以我的问题是:
地址0x804844c的“对象”是什么。
- 不能是简单的
offsetOf(),因为这是一个很大的偏移量。 - 它不能是 vtbl 的地址(或 vtbl 中条目的地址),因为我认为 vbtl 是与实例化对象相关联的实体,而不是与类相关联。
- 不能是加载函数实现代码的地址。因为相同的指针在与派生对象一起应用时可以表现出多态性。
那么地址0x804844c处的对象是什么,在应用->*或.*运算符时,它在将指向成员函数的指针转换为实际函数地址的作用是什么?
【问题讨论】:
-
函数不是 C++ 语言标准使用该术语的意义上的“对象”。请注意,成员函数通常实现为带有附加参数的普通函数(对象变为
this)。在这些实现中,它们不驻留在类实例本身中,而是与代码段中的其他(免费)函数一起。 -
“它不能是加载函数实现代码的地址。因为相同的指针在与派生对象一起应用时可以表现出多态性。” 参见,例如this answer
标签: c++