C++;我错过了什么? 我正在学习C++,想构建类似于C++事件的东西来处理嵌入式C++项目中的中断。

C++;我错过了什么? 我正在学习C++,想构建类似于C++事件的东西来处理嵌入式C++项目中的中断。,c++,templates,polymorphism,C++,Templates,Polymorphism,到目前为止,我提出了一个解决方案,几乎满足了我的需求。但是我需要一些多态性方面的帮助(?)。下面的代码片段是再现我的情况的一个最小示例: #include <iostream> struct Event { }; struct EventHandler { virtual void Esr (const Event& I) { } }; struct EventSender { EventSender (EventHandl

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

#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));
    }
 };
#include <iostream>

struct Event { 
    virtual void operator()() const { std::cout << "Event\n"; }
};

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

struct EventSender {
    template <typename T>
    void SendEvent (const T& t) const {
        handler.Esr(t);
    }

    EventHandler handler;
};

struct SpecialEvent : public Event { 
    virtual void operator()() const override { std::cout << "Special Event\n"; }
};

int main() {
    EventHandler handler;
    EventSender sender;

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

    /* Invoke indirectly  */
    sender.SendEvent (Event ());
    sender.SendEvent (SpecialEvent ());  // Expected cout msg: "SpecialEvent"
}
这就是为什么你最终选择了错误的方法


顺便说一句:我的回答是为了解释你看到了什么,并给你一个解决眼前问题的方法。Jerry Coffin的回答为您提供了一种从长远来看对您更有效的替代方法。

首先,您不能强制引用基类的后代。 您需要使用指向该类型的指针,并使用
dynamic\u cast

所以,你有

EventSender sender (handler);
main()
中。
sender
的构造函数绑定到
MyHandler
的基类
EventHandler
,因为这是
MyHandler
的构造函数中的参数类型(=
EventHandler::EventHandler
)。因此,调用了
EventHandler.Esr(const-Event&)
,它恰好是虚拟的,因此有一个指向
MyHandler.Esr(const-Event&)
的指针


请注意,从技术上讲,
Esr(const-Event&)
Esr(const-specialvent&)
是两种不同的方法;它们恰好使用了相同的名称。

这里您尝试使用重载,而不是经典的(基于虚拟函数的)多态性

你想要的(至少据我所知)是直接使用
处理程序
和通过
发送方
间接调用它之间本质上相同的行为。发生的变化在
事件
特殊事件
之间

在这种情况下,经典多态性将涉及
事件中的一个虚拟函数,该函数在
SpecialEvent
中被重写:

struct Event { 
    virtual void operator()() const { std::cout << "Event\n"; }
};

struct SpecialEvent : public Event { 
    virtual void operator()() const override { std::cout << "Special Event\n"; }
};

不确定这是否与问题有关,但为什么要将事件实例传递给
SendEvent
,然后在
SendEvent
中忽略此参数,但将新的
event
实例传递给
Esr
?解决此类问题的正确工具是调试器。在询问堆栈溢出之前,应该逐行检查代码。如需更多帮助,请阅读。至少,您应该[编辑]您的问题,以包括一个重现您的问题的示例,以及您在调试器中所做的观察。一个有趣的问题:一步走向答案,但不是完整答案,因此需要注释:通过替换{}is=0,使Esr方法纯虚拟;在方法声明中。@πάνταῥεῖ 您希望他在调试器中看到哪些尚未发现的内容?他很好地确定了实际调用的方法。现在他在问“为什么?”我想你把多态性和重载混为一谈了。
#include <iostream>

struct Event { 
    virtual void operator()() const { std::cout << "Event\n"; }
};

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

struct EventSender {
    template <typename T>
    void SendEvent (const T& t) const {
        handler.Esr(t);
    }

    EventHandler handler;
};

struct SpecialEvent : public Event { 
    virtual void operator()() const override { std::cout << "Special Event\n"; }
};

int main() {
    EventHandler handler;
    EventSender sender;

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

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