c++ - "upcast"方法指针并将其与基类指针一起使用是否安全?

标签 c++ polymorphism pointer-to-member

假设我有一个可以保存基类方法地址的指针类型。我可以将子类方法的地址分配给它并期望它正常工作吗?在我的例子中,我将它与基类指针一起使用,对象的动态类型是派生类。

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 时是这样说的:

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% 确定上面的文字是否真的适用于我的示例代码中的情况。

最佳答案

这是有效的。

If class B contains the original member,

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

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

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

the resulting pointer to member points to the original member

条款 5.2.9 9 说只有当你也可​​以向下转型时你才能向上转型,如 § 4.11 中所指定:

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 的继承图中只出现一次就可以向下转型。

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

关于c++ - "upcast"方法指针并将其与基类指针一起使用是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4272909/

相关文章:

c++ - 为什么获取成员函数指针值需要在类内部进行类名限定?

c++ - 超出范围的局部变量......我认为

c++ - 如何正确关闭用 fdopen 打开的套接字?

c++ - vector 的排序

java - 子类中是否存在父类(super class)构造函数(但不被继承)?

oop - 多态性与继承作为 oop 的支柱

c++ - 根据字符串选择成员函数

c++:可以使用boost::bind将成员函数转换为预期的函数指针签名吗?

c++ - QTextToSpeech 设置默认 QLocale

c# - 通过接口(interface)访问静态属性