其他分享
首页 > 其他分享> > c – 向上转换函数指针是否安全?

c – 向上转换函数指针是否安全?

作者:互联网

我有基类Object和Event

class Object
{
//...
};

class Event
{
};

还有一个函数指针的typedef

typedef void (Object::*PF) (Event*);

还有一个不相关的类,它存储两个指针

class Dispatcher
{
public:
    Dispatcher (Object* obj, PF pf) : _obj (obj), _pf (pf)

    void call (Event* event)
    {
        _obj->*pf (event);
    }

    Object* _obj;
    PF _pf;
};

然后我有一个具体的对象和一个具体的事件

class ConcreteEvent : public Event
{
};

class ConcreteObject : public Object
{
public:
   void handle (ConcreteEvent* event)
   {
      // Do something specific for ConcreteEvent
   }
};

然后像这样称呼它

ConcreteObject* obj = new ConcreteObject();
Dispatcher dispatcher (obj, static_cast<PF>(&ConcreteObject::handle));

ConcreteEvent* event = new ConcreteEvent ();
dispatcher.call (event);

我保证将始终使用正确的事件调用调度程序,即,当它封装的函数指针实际上采用SomeOtherConcreteEvent时,我不会调用调度程序并将其传递给ConcreteEvent

问题是:这是否有效?在linux和mingw上,gcc 4.7当然可行.

解决方法:

从C 11标准,第4.11.2节:

A prvalue of type “pointer to member of B of type cv T”, where B is a class type, can be converted to a
prvalue 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, or a base class of a virtual
base class of D, a program that necessitates this conversion is ill-formed. The result of the conversion refers
to the same member as the pointer to member before the conversion took place, but it refers to the base
class member as if it were a member of the derived class.

所以是的,这应该是安全的.

编辑:所以,如果你真的意味着向下转换:这也是合法的,根据C 11 5.2.9.12:

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 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.
69

标签:upcasting,member-function-pointers,c
来源: https://codeday.me/bug/20190901/1781613.html