()操作员过载

() Operator overloading

本文关键字:操作员      更新时间:2023-10-16

这个问题以前被问过,但没有得到满意的回答。

我有一个充当事件处理程序的类,我希望有一个很好的语法来在事件之外调用事件处理程序。这归结为覆盖()运算符。我目前有

class EventHandler
{
public:
    void Call(void* sender, EventArgs e);
    void operator() (void* sender, EventArg e){ Call(sender, e); }
};

这很好用。我可以通过调用事件处理程序

EventHandler EH;
EH(nullptr, EventArgs::Empty());

我的问题在于,我通常将事件处理程序存储在堆中,因此我需要

EventHandler* EH;
EH(nullptr, EventArgs::Empty());  // error but this is the syntax I'm hoping for

但这只能通过来实现

EventHandler* EH;
(*EH)(nullptr, EventArgs::Empty());  // no error

如何重写()运算符以使其与指向EventHandler对象的指针一起工作?我看到了一些看起来像是重载->()运算符而不仅仅是()运算符的事情,但我没能理解它。

运算符->()不存在。

有两种方法可以呼叫接线员。

EventHandler* EH;
(*EH)(nullptr, EventArgs::Empty());

EventHandler* EH;
EH->operator()(nullptr, EventArgs::Empty());

这与operator=或任何其他操作员的工作方式相同

"我的问题在于我通常将事件处理程序存储在堆上,所以我需要"

这是有原因的吗?如果EH涉及大量的状态,那么也许您可以构建一个包装类,将状态放在堆上,但它本身被分配为对象。这将允许重载operator()()并获得所需的语法,同时转发到底层实现。基本上重构为Pimpl,以便在接口中使用的对象中获得所需的语法。

将堆分配详细信息封装在正则类型中,并使用正则类型而不是指针通常是一个好主意。

class EventHandler_Impl {
public:
        void Call(void* sender, EventArgs e);
        void operator() (void* sender, EventArg e){ Call(sender, e); }
};

然后我们写:

struct EventHandler {
  void operator()(void* sender, EventArg e){ (*pImpl)(sender, e); }
private:
  std::unique_ptr<EventHandler_Impl> pImpl;
};

我们有一个"正则"类型EventHandler,它存储一个指向"实际"类的指针。它具有转发到CCD_ 5的方法。

这个类的状态只是一个指针。当pImpl超出范围时,它会自动删除。std::unique_ptr有一个指针的开销(您应该存储它),只是当pImpl对象超出范围时它会破坏它。

您可以使其仅移动,也可以手动实现复制构造函数(为_Impl接口添加克隆自身的能力)。

这有点像样板。

您可以取消在_Impl中写入方法,只需将它们写入常规类型,如果您选择的话,通过pImpl指针使它们只访问状态。

你不能。EventHandler*是指向一个类型的指针,它根本不可调用。

您可以使用另一个函子作为包装器,只需要以稍微不同的方式调用它。

struct EventHandlerCaller
{
   void operator() (EventHandler* eh, void* sender, EventArg& e)
   { 
     eh->operator()(nullptr, sender, e);
   }
}
static EventHandlerCaller caller;
EventHandler* EH;
caller(eh, nullptr, EventArgs::Empty());