首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >指向成员转换的指针

指向成员转换的指针
EN

Stack Overflow用户
提问于 2010-11-28 03:06:32
回答 1查看 2.9K关注 0票数 14

我刚刚在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成员的指针类型?

代码语言:javascript
复制
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,它的答案只涉及从指针到基类成员到从指针到派生类成员的转换。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2010-11-28 17:12:48

你写的代码是完全有效的。它没有什么问题(除了Derived::a是私有的)。它是良好的形式和行为的定义(到目前为止)。正如标准中引用的部分所述,使用显式static_cast (这正是您所要做的)向上转换成员指针是完全合法的。5.2.9/9从来没有说指出的成员必须在基类中。

此外,正如您从标准中正确引用的那样,在指针取消引用时,而不是在初始化时,需要在对象中出现实际的成员。当然,这取决于成员访问操作符(->*.*)左侧使用的对象的动态类型。只有在运行时才知道类型,因此编译器无法检查.

这一要求仅作为说明列入5.2.9/9,但在5.5/4中以更正式的形式重申了这一要求

4如果对象的动态类型不包含指针引用的成员,则行为未定义。

因此,例如,在示例的上下文中,下面的代码行是格式良好的

代码语言:javascript
复制
Base b;
b.*pa; // 1

Derived d;
d.*pa; // 2

Base *pb = &d;
pb->*pa; // 3

但是,第一个取消引用会产生未定义的行为(因为对象b不包含成员),而第二个和第三个都是完全合法的。

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4295117

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档