标签:
对于普通指针变量来说,其值是它所指向的地址,0表示空指针。
而对于数据成员指针变量来说,其值是数据成员所在地址相对于对象起始地址的偏移值,空指针用-1表示。例:
代码示例:
函数成员指针与普通函数指针相比,其size为普通函数指针的两倍(x64下为16字节),分为:ptr和adj两部分。
(1) 非虚函数成员指针
ptr部分内容为函数指针(指向一个全局函数,该函数的第一个参数为this指针),adj部分始终为0。例:
代码示例:
(2) 虚函数成员指针
ptr部分内容为虚函数对应的函数指针在虚函数表中的偏移地址加1(之所以加1是为了用0表示空指针),而adj部分为调节this指针的偏移字节数。例:
说明:
代码示例:
extern "C" int printf(const char*, ...); struct A { virtual void foo() { printf("A::foo(): this = 0x%p\n", this); } }; struct B { virtual void bar() { printf("B::bar(): this = 0x%p\n", this); } }; struct C : public A, public B { virtual void quz() { printf("C::quz(): this = 0x%p\n", this); } }; void (A::*pafoo)() = &A::foo; // ptr: 1, adj: 0 void (B::*pbbar)() = &B::bar; // ptr: 1, adj: 0 void (C::*pcfoo)() = &C::foo; // ptr: 1, adj: 0 void (C::*pcquz)() = &C::quz; // ptr: 9, adj: 0 void (C::*pcbar)() = &C::bar; // ptr: 1, adj: 8 #define PART1_OF_PTR(p) (((long*)&p)[0]) #define PART2_OF_PTR(p) (((long*)&p)[1]) int main() { printf("&A::foo->ptr: 0x%lX, ", PART1_OF_PTR(pafoo)); // 1 printf("&A::foo->adj: 0x%lX\n", PART2_OF_PTR(pafoo)); // 0 printf("&B::bar->ptr: 0x%lX, ", PART1_OF_PTR(pbbar)); // 1 printf("&B::bar->adj: 0x%lX\n", PART2_OF_PTR(pbbar)); // 0 printf("&C::foo->ptr: 0x%lX, ", PART1_OF_PTR(pcfoo)); // 1 printf("&C::foo->adj: 0x%lX\n", PART2_OF_PTR(pcfoo)); // 0 printf("&C::quz->ptr: 0x%lX, ", PART1_OF_PTR(pcquz)); // 9 printf("&C::quz->adj: 0x%lX\n", PART2_OF_PTR(pcquz)); // 0 printf("&C::bar->ptr: 0x%lX, ", PART1_OF_PTR(pcbar)); // 1 printf("&C::bar->adj: 0x%lX\n", PART2_OF_PTR(pcbar)); // 8 return 0; }
参考:
C++ ABI for Itanium: 2.3 Member Pointers
标签:
原文地址:http://www.cnblogs.com/zhehan54/p/5582135.html