简体   繁体   English

成员函数指针转换,从派生类到基类

[英]Member function pointer cast, from Derived to Base class

I'm doing the following:我正在做以下事情:

  • Taking a member function pointer with 3 params from a derived class .派生类中获取具有3 个参数的成员函数指针。
  • Casting it to a member function pointer from the base class with 0 params .使用0 params将其转换为来自基类的成员函数指针。
  • Casting it to the base class with the 3 params back.将它转换为基类返回3 个参数
  • Calling it.调用它。

It works fine (so far), but should i keep it?它工作正常(到目前为止),但我应该保留它吗?

Description of current code:当前代码说明:

EventsWarehouse is used to store and invoke events: EventsWarehouse 用于存储和调用事件:

#include <iostream>
#include <functional>
#include <unordered_map>

class EventsWarehouse
{
public:
    typedef std::tuple<AView*, void (AView::*)()>           box_t;
    typedef std::unordered_multimap<std::string, box_t>     boxes_t;

    void        storeEvent(std::string const &event, AView *v, void (AView::*callback)())
        {
            this->_events.insert(std::make_pair(event, std::make_tuple(v, callback)));
            return ;
        }

    template<typename... Args>
    bool        fireEvent(std::string const &event, Args... args)
        {
            auto                it = this->_events.find(event);
            AView               *v;
            void                (AView::*callback_)();
            void                (AView::*callback)(Args...);

            for (; it != this->_events.end(); it++)
            {
                v = std::get<0>(it->second);
                callback_ = std::get<1>(it->second);
                /*
                ** CAST #2
                ** <void (AView::*)()>
                **  to
                ** <void (AView::*)(std::string, int, double)>
                **  before call
                */
                callback = reinterpret_cast<void (AView::*)(Args...)>(callback_);
                (v->*callback)(args...);
            }
            return (true);
        }
private:
    boxes_t         _events;

};

View classes stored in the above class:查看存储在上述类中的类:

class AView
{
protected:
    AView(){}
};

class DerivedView : public AView
{
public:
    void    fooCallback(std::string s, int i, double d)
        {
            std::cout << "DerivedView::fooCallback received " << s << ", " << i << ", " << d << std::endl;
            return ;
        }
};

Main:主要的:

int                         main(void)
    {
        DerivedView     dv;
        EventsWarehouse ewh;

        /*
        ** CAST #1
        ** <void (DerivedView::*)(std::string, int, double)>
        **  to
        ** <void (AView::*)()>
        **  for storing purpose
        */
        ewh.storeEvent("event 1", &dv, reinterpret_cast<void (AView::*)()>(&DerivedView::fooCallback));
        ewh.fireEvent("event 1", std::string("Hello World"), 42, 84.42);
        return (0);
    }

According to draft n4296 for C++11 specification, 5.2.10 Reinterpret cast [expr.reinterpret.cast] §10根据 C++11 规范的 n4296 草案,5.2.10 Reinterpret cast [expr.reinterpret.cast] §10

A prvalue of type “pointer to member of X of type T1” can be explicitly converted to a prvalue of a different type “pointer to member of Y of type T2” if T1 and T2 are both function types or both object types.72 The null member pointer value (4.11) is converted to the null member pointer value of the destination type.如果 T1 和 T2 都是函数类型或对象类型,则“指向类型 T1 的 X 成员的指针”类型的纯右值可以显式转换为不同类型的“指向类型 T2 的 Y 成员的指针”的纯右值。 72空成员指针值(4.11)被转换为目标类型的空成员指针值。 The result of this conversion is unspecified, except in the following cases:此转换的结果未指定,但以下情况除外:

— converting a prvalue of type “pointer to member function” to a different pointer to member function type and back to its original type yields the original pointer to member value. — 将“指向成员函数的指针”类型的纯右值转换为指向成员函数类型的不同指针并返回其原始类型会产生指向成员值的原始指针。

— converting a prvalue of type “pointer to data member of X of type T1” to the type “pointer to data member of Y of type T2” (where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer to member value. — 将“指向类型 T1 的 X 数据成员的指针”类型的纯右值转换为类型“指向类型 T2 的 Y 数据成员的指针”(其中 T2 的对齐要求不比 T1 的对齐要求更严格)并返回到其原始类型产生指向成员值的原始指针。 the conversion to a pointer to member function with no parameters and back to a member functions with correct parameters should give back original pointer.转换为指向没有参数的成员函数的指针并返回到具有正确参数的成员函数应该返回原始指针。

IMHO, the problem is that fooCallback is only defined on DerivedView class, and as such it is not a member function of class AView .恕我直言,问题是fooCallback仅在DerivedView类上定义,因此它不是AView的成员函数。

This would be correct:这是正确的:

void (AView::*p)() = reinterpret_cast<void (AView::*)()>(&DerivedView::fooCallback);
void (DerivedView::*callback)(std::string, int, double) =
       reinterpret_cast<void (DerivedView::*)(std::string, int, double)>(p);
v->callback("Hello World"), 42, 84.42);

provided v is a AView * pointing to a DerivedView提供v是一个AView *指向一个DerivedView

But as you end converting a void (DerivedView::*)(std::string, int, double) to a void (AView::*)(std::string, int, double) they are different type so conversion is unspecified但是当您结束将void (DerivedView::*)(std::string, int, double)转换为void (AView::*)(std::string, int, double)它们的类型不同,因此未指定转换

It works, because common implementation for non static non virtual member functions is simply a normal (non member) function with a hidden parameter being this .它有效,因为非静态非虚拟成员函数的常见实现只是一个普通(非成员)函数,隐藏参数为this So the pointer to member just stores the address of that function and correctly calls it with a pointer to a DerivedView giving expected result.因此,指向成员的指针仅存储该函数的地址,并使用指向DerivedView的指针正确调用它,从而给出预期的结果。 But a different implementation could also store the actual type and raise an exception (or do anything else).但是不同的实现也可以存储实际类型并引发异常(或做任何其他事情)。

TL/DR: As you end with a conversion from void (DerivedView::*)(std::string, int, double) to void (AView::*)(std::string, int, double) you do not cast to pointer to member to its original type and invoke undefined behaviour. TL/DR:当您以从void (DerivedView::*)(std::string, int, double)void (AView::*)(std::string, int, double)的转换结束时,您void (DerivedView::*)(std::string, int, double)转换指向指向其原始类型的成员并调用未定义的行为。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无法将“指向派生类的成员指针”转换为“指向基类的成员指针” - Cannot cast “member pointer to derived class” to “member pointer to base class” C ++将派生类的成员指针转换为基类指针 - c++ cast member pointer of derived Class to base class pointer 将派生类中的成员函数的指针强制转换为抽象成员函数的指针 - cast a pointer to member function in derived class to a pointer to abstract member function 为什么我不能将指向Derived类成员函数的指针强制转换为类Base? - why can't I cast a pointer to Derived class member function to the same but of class Base? C ++如何在不使用static_cast或dynamic_cast的情况下从基类指针访问派生类成员? - C++ How to access derived class member from base class pointer without using a static_cast or dynamic_cast? 函数在派生类中但不在基类中,指向基类的指针--&gt;“不是成员”错误 - function in derived but not in base class, pointer to base --> "not a member" error 如何将指向基类成员的指针强制转换为指向派生类的同一成员的指针 - How to cast a pointer to member of base class to a pointer to the same member of derived class 将指向派生类成员变量的指针转换为指向基类成员变量的指针是否合法? - Is it legal to cast a pointer-to-derived-class-member-variable to a pointer-to-base-class-member-variable? 使用基类函数指针访问派生类成员函数 - Using base class function pointer to access derived class member function 如何注册派生的 class 成员 function 指针与基数 class - How to register a derived class member function pointer with a base class
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM