我刚刚在c++03标准草案中找到了与指向成员转换的指针相关的以下段落。
4.11/2指向成员转换的指针
类型“指针到cv T类型的B成员的指针”的r值,其中B是类类型,可以转换为类型“指针到cv T类型的D的成员”的rvalue,其中D是B的派生类(第10条)。如果B是不可访问的(第11条),模糊的(10.2)或虚拟的(10.1) D基类,需要进行这种转换的程序是错误的。转换的结果在转换之前引用同一个成员作为指向成员的指针,但它引用基类成员,就好像它是派生类的成员一样。结果引用D的B实例中的成员,因为结果具有类型“指针到cv类型的D成员”,因此可以用D对象取消引用。结果就像指向B成员的指针与D的B子对象取消引用一样,空成员指针值被转换为目标类型的空成员指针值。
5.2.9/9 static_cast
类型的r值“cv1 T类型的D成员的指针”可以转换为“cv2 T类型的B成员的指针”类型的rvalue,其中B是D的基类(第10条),如果存在从“指针到T类型的B成员的指针”的有效标准转换(4.11),而cv2是与目标类型的空成员指针值(4.11)相同的cv-限定或大于cv-限定值,则为空成员指针值(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,它的答案只涉及从指针到基类成员到从指针到派生类成员的转换。
发布于 2010-11-28 17:12:48
你写的代码是完全有效的。它没有什么问题(除了Derived::a是私有的)。它是良好的形式和行为的定义(到目前为止)。正如标准中引用的部分所述,使用显式static_cast (这正是您所要做的)向上转换成员指针是完全合法的。5.2.9/9从来没有说指出的成员必须在基类中。
此外,正如您从标准中正确引用的那样,在指针取消引用时,而不是在初始化时,需要在对象中出现实际的成员。当然,这取决于成员访问操作符(->*或.*)左侧使用的对象的动态类型。只有在运行时才知道类型,因此编译器无法检查.
这一要求仅作为说明列入5.2.9/9,但在5.5/4中以更正式的形式重申了这一要求
4如果对象的动态类型不包含指针引用的成员,则行为未定义。
因此,例如,在示例的上下文中,下面的代码行是格式良好的
Base b;
b.*pa; // 1
Derived d;
d.*pa; // 2
Base *pb = &d;
pb->*pa; // 3但是,第一个取消引用会产生未定义的行为(因为对象b不包含成员),而第二个和第三个都是完全合法的。
https://stackoverflow.com/questions/4295117
复制相似问题