根据ABI http://refspecs.linux-foundation.org/cxxabi-1.83.html#member-pointers,
指向数据成员的指针是相对于基地址的偏移量
包含它的类对象... NULL 指针表示为 -1
但是,根据 c++ 标准(我有修订版 4296,它位于4.11/1),
该类型的空成员指针值...是可区分的
从任何指向不是从空指针常量创建的成员的指针
-1 可以是有效的偏移量。
考虑这种情况:
#include <iostream>
using namespace std;
struct A {
char a,b,c,d,e,f,g,h;
};
struct B {
int i;
};
struct C : A,B {};
int main() {
char C::*p=&C::h;
char B::*q = static_cast<char B::*>(p);
cout<< (q==nullptr) <<endl; //prints 1
}
在此代码中,我的编译器(x86_64-linux-gnu 上的 g++4.9.2)放置h
在最后一个字节A
、和地点B
就在之后A
in C
。因此,偏移量为C::A::h
从基地址C::B
is -1.
(转换是合法的,它的结果可以用在动态类型 C 的对象上,即使它的静态类型是 B。标准说(5.2.9/12) “虽然 B 类不需要包含原始成员,但通过指向成员的指针执行间接操作的对象的动态类型必须包含原始成员”)
我有什么误解吗?
(我怀疑我的误解是关于“包含原始成员的类”这句话(5.2.9/12) - 考虑到C::h
,该短语可能指的是A
并且不C
,但标准明确指出(10/2)“基类的成员也被视为派生类的成员”)