C ++多态性:我缺少什么?

平台1

我正在学习c ++,并希望构建与C#事件类似的东西来处理嵌入式c ++项目中的中断。

到目前为止,我想出了一种解决方案,几乎可以满足我的需求。但是我需要多态性(?)的帮助。以下代码段是重现我的情况的一个最小示例:

#include <iostream>       

struct Event
  { };

struct EventHandler
  {
    virtual void Esr (const Event& I) { }
  };

struct EventSender
  {
    EventSender (EventHandler& Handler) : _Handler (Handler) { }

    template <typename T>
    void SendEvent (const T&) const
      {
        _Handler.Esr (T ());
      }

    EventHandler& _Handler;
  };

struct SpecialEvent : public Event
  { };

struct MyHandler : public EventHandler
  {
    void Esr (const Event& I) override { std::cout << "Event" << std::endl; }
    void Esr (const SpecialEvent& I) { std::cout << "SpecialEvent" << std::endl; }
  };            

int main()
  {
    MyHandler handler;
    EventSender sender (handler);

    /* Invoke directly  */
    handler.Esr (Event ());
    handler.Esr (SpecialEvent ());

    /* Invoke indirectly  */
    sender.SendEvent (Event ());
    sender.SendEvent (SpecialEvent ());  // Expected cout msg: "SpecialEvent"

    return 0;
  }

预期的控制台输出:

Event
SpecialEvent
Event
SpecialEvent

实际控制台输出:

Event
SpecialEvent
Event
Event

我不知道的编译器/链接器是什么?

戴尔·威尔逊

MyHandler中有两个方法。其中一个覆盖基类方法,另一个不覆盖。

一种解决方案是在基类中声明两个方法:

struct EventHandler
{
    virtual void Esr (const Event& I) = 0;
    virtual void Esr (const SpecialEvent& I) = 0;
};

这样,编译器可以使用参数的类型在EventHandler级别解析该方法。

如果要避免所有派生类都必须重载两个方法的要求,可以执行以下操作:

 struct EventHandler
 {
    virtual void Esr (const Event& I) = 0;
    virtual void Esr (const SpecialEvent& I)
    {
        // if not overridden, use the non-specialized event handler.
        Esr(reinterpret_cast<const Event &>(I));
    }
 };

要回答您的问题:

我不知道的编译器/链接器是什么?

在C ++中,方法调用在编译/链接时解析为1)调用特定代码块(方法主体),或2)通过称为vtable的隐藏数据结构进行间接调用。实际的vtable是在运行时确定的,但是编译器必须决定要在表中使用哪个条目进行调用。(Google vtable提供了有关它们是什么以及如何实现的更多信息。)

它必须基于允许知道的解决方案。在这种情况下,基于调用该方法的指针或引用的类型。请注意,这不一定是实际对象的类型。

在您的情况下,当您通过调用handler方法时,允许编译器知道在中声明的两个方法,MyHandler以便可以选择所需的方法,但是当调用通过时sender,它必须查找在中声明的方法EventSender中仅声明了一种方法EventSender幸运的是,该参数可以强制为,const Event &以便编译器能够使用该方法。因此,它将vtable条目用于该方法。因此,它为MyHandler[在运行时]找到了vtable并将vtable条目用于

 Esr (const Event& I)

这就是你如何在错误的方法结束。

顺便说一句:我的答案是要解释您所看到的内容,并为您解决当前问题的方法。杰里·科芬(Jerry Coffin)的答案为您提供了另一种方法,该方法从长远来看应该对您更好。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章