考虑这种类型层次结构:
struct A {
int x;
};
struct B : A {
int y;
};
&B::y
的类型为int B::*
,但&B::x
的类型为int A::*
。它可以转换为int B::*
,这是我需要的,但我需要明确地执行转换。
是否有一种方便的方法可以推断出类型是指向我指定的类成员的指针?毕竟,如果我想要A::*
到x
我可以&A::x
。
答案 0 :(得分:0)
在虚拟继承的情况下,这种转换是不可能的。假设
struct A {
int x;
};
struct B : virtual A {
int y;
};
和两个函数,
int f(B* pB) {
int A::*pX = &A::x; // or &B::x, identical but clearer this way
return pB->*pX;
}
int g(B* pB) {
int B::*pY = &B::y;
return pB->*pY;
}
f(B*)
需要进行vtable查找才能在A
内找到*pB
个实例的基指针,而g(B*)
仅将偏移应用于pB
。因此,对象&A::x
不能表示为类型int B::*
的实例,它需要一个不同的运行时逻辑来使用指向B
而不是int B::*
的指针进行评估。
即使B
是此处和现在派生程度最高的类,也可以在另一个编译单元中定义另一个继承C
和A
的类B
并希望将C*
传递给f()
。因此,A
中B
的偏移量不能用于修复。
有人可能会争辩说,如果没有虚拟继承,或者在匿名命名空间中,语言可以允许转换,或者......但是可能更容易一致地禁止它。