进行“ upcast”是否安全?方法指针,并与基类指针一起使用? [英] Is it safe to "upcast" a method pointer and use it with base class pointer?

查看:89
本文介绍了进行“ upcast”是否安全?方法指针,并与基类指针一起使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个指针类型,可以容纳基类方法的地址。我可以为其分配子类方法的地址并期望它正常工作吗?在我的情况下,我将其与基类指针一起使用,并且对象的动态类型是派生类。

Let's say I have a pointer type that can hold the address of a base class method. Can I assign the address of a subclass method to it and expect it to work correctly? In my case I'm using it with a base class pointer and the dynamic type of the object is the derived class.

struct B
{
    typedef void (B::*MethodPtr)();
};

struct D: public B
{
    void foo() { cout<<"foo"<<endl; }
};

int main(int argc, char* argv[])
{
    D d;
    B* pb = &d;

    //is the following ok, or undefined behavior?
    B::MethodPtr mp = static_cast<B::MethodPtr>(&D::foo);
    (pb->*mp)();
}

标准在谈论static_cast时是这样说的:

The standard says this when talking about static_cast:

5.2.9.9 可以将类型指向cv1 T类型的D的成员的指针的右值转换为类型cv2 B的成员的指针的右值。 T,其中B是D的基类(第10节),如果存在从类型T的B的指针到成员到类型T的D的指针的有效标准转换(4.11),则cv2与cv1具有相同的
cv资格,或更高的cv资格。 63)空成员指针值(4.11)转换为目标类型的空成员指针值。如果类B包含原始成员,或者是包含原始成员的类的基类或派生类,则指向成员的结果指针将指向原始成员。否则,强制转换的结果是不确定的。 [注:尽管类B需要
不包含原始成员,但要取消引用成员指针的对象的动态类型必须包含原始成员;见5.5。]
5.2.9.9 An rvalue of type "pointer to member of D of type cv1 T" can be converted to an rvalue of type "pointer to member of B of type cv2 T", where B is a base class (clause 10) of D, if a valid standard conversion from "pointer to member of B of type T" to "pointer to member of D of type T" exists (4.11), and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1. 63) The null member pointer value (4.11) is converted to the null member pointer value of the destination type. If class B contains the original member, or is a base or derived class of the class containing the original member, the resulting pointer to member points to the original member. Otherwise, the result of the cast is undefined. [Note: although class B need not contain the original member, the dynamic type of the object on which the pointer to member is dereferenced must contain the original member; see 5.5.]

和往常一样,我很难理解标准。有点儿说可以,但是我不确定100%以上的文字是否真的适用于我的示例代码中的情况。

As always, I'm having such a hard time deciphering the standard. It kinda says that it is ok, but I'm not 100% sure if the above text really applies to the situation in my example code.

推荐答案

有效。


如果B类包含原始成员,

If class B contains the original member,

B不包含D :: Foo,所以不。

B doesn't contain D::Foo, so no.


或为基数包含原始成员的类的[...]

or is a base [...] of the class containing the original member

B是D的底,因此成立。结果:

B is a base of D, so this holds. As a result:


指向成员的结果指针指向原始成员

the resulting pointer to member points to the original member

条款5.2.9 9说,只有在也可以向下转换的情况下,您才能向上转换,如第4.11节中所述:

Clause 5.2.9 9 says you can upcast only if you can also downcast, as specified in § 4.11:


类型为指向cv T类型的B的成员的指针的右值(其中B是类类型)可以转换为类型为指向cv T类型D的成员的指针的右值,其中D是B的派生类(第10条)。如果B是D的不可访问的(第11条),模棱两可的(10.2)或虚拟的(10.1)基类,则需要进行此转换的程序格式错误。

An rvalue of type "pointer to member of B of type cv T," where B is a class type, can be converted to an rvalue of type "pointer to member of D of type cv T," where D is a derived class (clause 10) of B. If B is an inaccessible (clause 11), ambiguous (10.2) or virtual (10.1) base class of D, a program that necessitates this conversion is ill-formed.

这只是说,只要B可以访问,不是虚拟的并且仅在D的继承图中出现一次,您就可以向下转换。

This just says you can downcast as long as B is accessible, isn't virtual and only appears once in D's inheritance diagram.

向上转换方法指针固有的危险是,您可以在实际类型为B的对象上调用 mp 。处理D :: *也处理D *,y您可以避免这种情况。

The danger inherent in upcasting method pointers is that you could call mp on an object whose actual type is B. As long as a code block that deals with D::* also deals with D*, you can avoid this.

这篇关于进行“ upcast”是否安全?方法指针,并与基类指针一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆