通过基类函数指针调用派生类 [英] Calling derived class through base class function pointer

查看:156
本文介绍了通过基类函数指针调用派生类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以通过基类函数 pointer 调用派生类,如下面的示例所示?

Can I call a derived class through a base class function pointer, as shown in the example below?

我知道我的示例可以工作,但是可以保证总是这样做(假设对象实际上实现了该功能!),或者这仅仅是我使用的编译器的特质?

I understand that my example works, but is it guaranteed to always do so (Assuming the object actually implements the function!), or is this just an idiosyncrasy of the compiler I'm using?

通过这种逻辑,不能简单地从"CBase"(在这种情况下为空,因此我认为没有开销)派生所有类并忽略函数指针中的类型吗?

By this logic can't one simply derive all their classes from "CBase" (which in this case is empty so I guess no overhead) and ignore the type in the function pointer?

#include <iostream>

struct CBase
{ 
};

struct CDerived : CBase
{
    void MyFunction()
    {
        std::cout << "Called OK" << std::endl;
    }
};

typedef void (CBase::*FunctionPointer)();


int main()
{
    CDerived* base = new CDerived();

    FunctionPointer pointer = static_cast<FunctionPointer>(&CDerived::MyFunction);
    (base->*pointer)();

    delete base;
}

使用场景示例: 一个派生类,它在基类中采用一个或多个指向回调"的指针.可以仅使用派生类定义回调类型,从而放弃对模板的需求吗?

Example usage scenario: A derived class that takes one or more pointers to "callbacks" in the base class. Can the callback type just be defined using the derived class and thus forgo the need for a template?

推荐答案

是的,保证可以正常工作.来自[expr.static.cast]:

Yes, it's guaranteed to work. From [expr.static.cast]:

指向 cv1 T类型的D的成员的指针"的prvalue可以转换为"pointer类型"的prvalue 到 cv2 T类型的B成员,如果 cv2 相同,则BD的基类(第10条) cv -资格 作为或大于cv1.70的cv资格如果没有从指针到B的成员"的有效标准转换 如果存在类型T"到指向类型T的D的成员的指针"(4.11),则程序格式不正确.空成员 指针值(4.11)转换为目标类型的空成员指针值.如果类B包含 原始成员,或者是包含原始成员的类的基类或派生类,其结果 指向成员的指针指向原始成员.

A prvalue of type "pointer to member of D of type cv1 T" can be converted to a prvalue of type "pointer to member of B of type cv2 T", where B is a base class (Clause 10) of D, if cv2 is the same cv-qualification as, or greater cv-qualification than, cv1.70 If no valid standard conversion from "pointer to member of B of type T" to "pointer to member of D of type T" exists (4.11), the program is ill-formed. 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.

在这种情况下,我们将指向void()类型的CDerived成员的指针转换为CBase ov类型的void()成员的指针. CBase是包含原始成员的类的基础,因此生成的指针指向原始成员.

In this case, we're converting a pointer to member of CDerived of type void() to a poitner to member of CBase ov type void(). CBase is a base of the class containing the original member, so the resulting pointer points to the original member.

来自[expr.mptr.oper]:

From [expr.mptr.oper]:

将pm-expression.* cast-expression缩写为E1.*E2E1被称为对象表达式.如果动态 E1的类型不包含E2所引用的成员,其行为是不确定的.

Abbreviating pm-expression.*cast-expression as E1.*E2, E1 is called the object expression. If the dynamic type of E1 does not contain the member to which E2 refers, the behavior is undefined.

在这种情况下,pointer指向原始成员的指针. base具有该成员.所以这很好.

In this case, pointer pointers to the original member. base has that member. So this is fine.

请注意,在您的示例中,base实际上是一个CDerived*.写作同样有效:

Note that in your example, base is actually a CDerived*. It would be just as valid to write:

CDerived d;
CBase* b = &d;

(b->*pointer)(); // ok - the dynamic type of b contains the member to which pointer refers

这篇关于通过基类函数指针调用派生类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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