【发布时间】:2010-11-28 03:06:32
【问题描述】:
我刚刚在 c++03 标准草案中找到了以下与指向成员转换的指针相关的段落。
4.11/2 指向会员转化的指针
“指向类型为 cv T 的 B 成员的指针”类型的右值,其中 B 是类类型,可以转换为类型为“指向类型为 cv T 的 D 成员的指针”类型的右值,其中 D 是B 的派生类(第 10 条)。如果 B 是 D 的不可访问(第 11 条)、模棱两可(10.2)或虚拟(10.1)基类,则需要进行这种转换的程序是格式错误的。转换的结果在转换发生之前引用与指向 member 的指针相同的成员,但它引用基类成员,就好像它是 派生类。结果引用了 D 的 B 实例中的成员。由于结果的类型为“指向类型为 cv T 的 D 成员的指针”,因此可以使用 D 对象取消引用。结果与使用 D 的 B 子对象取消引用 B 的成员的指针相同。空成员指针值转换为目标类型的空成员指针值。52)
5.2.9/9 static_cast
“指向类型为 cv1 T 的 D 成员的指针”类型的右值可以转换为“指向类型为 cv2 T 的 B 成员的指针”类型的右值,其中 B 是 D 的基类(第 10 条) ,如果存在从“指向 T 类型 B 成员的指针”到“指向 T 类型 D 成员的指针”的有效标准转换 (4.11),并且 cv2 与 cv-qualification 相同或大于 cv-qualification, cv1.63) 将空成员指针值(4.11)转换为目标类型的空成员指针值。如果类 B 包含原始成员,或者是包含原始成员的类的基类或派生类,则指向成员的结果指针指向原始成员。否则,强制转换的结果是未定义的。 [注:虽然B类需要 不包含原始成员,取消引用指向成员的指针的对象的动态类型必须包含原始成员;见 5.5。 ]
所以这是我的问题。正如 5.2.9/9 所说,如果存在 4.11/2 中描述的有效转换,则指向 D 成员的指针可以转换为指向 B 成员的指针。这是否意味着如果 D 的成员 'm' 不是从 B 继承的,则指向成员 'm' 的指针不能转换为指向 B 成员的指针的类型?
class Base { };
class Derived : public Base
{
int a;
};
typedef int Base::* BaseMemPtr;
BaseMemPtr pa = static_cast<BaseMemPtr>(&Derived::a); // invalid, as per 5.2.9/9 ?
在 5.2.9/9 的注释中还说,虽然 B 类不需要包含原始成员,但解除引用成员指针的对象的动态类型必须包含原始成员。
我对段落的措辞感到困惑。上面的代码有效吗?
我搜索了该站点,并且有一个类似的问题,c++ inheritance and member function pointers,其答案仅涵盖了从指向基类成员的指针转换为指向派生类成员的指针的情况。
【问题讨论】:
-
您正在将指向数据成员值的指针分配给指向成员函数变量的指针。否则,是的,“强制转换的结果是未定义的。”