2014-10-31 82 views
2

此問題已被詢問,但未得到滿意答覆。()操作員超載

我有一個類作爲一個事件處理程序,我想有一個很好的語法來調用事件以外的事件處理程序。這個歸結爲重寫()運算符。我目前有

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對象的指針一起工作?我已經看到了一些看起來像重載 - >()運算符而不僅僅是()運算符的東西,但我一直無法理解它。

+1

也許不存在令人滿意的答案的原因是因爲它不可能?編譯器會識別指向函數的指針,並允許您放棄取消引用,但指向類對象的指針沒有對應的快捷方式。 – 2014-10-31 16:07:32

+0

您可以將非空指針轉換爲引用以獲取您正在查找的語法。 – quamrana 2014-10-31 22:16:26

回答

7

運營商->()不存在。

有兩種方法可以調用操作員。

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

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

這工作在相同的方式operator=或任何其他操作

0

你不能。 EventHandler*是一個指向類型的指針,它根本不可調用。

2

「我的問題在於我通常存儲在事件處理程序堆上,所以我需要「

這是有原因嗎?如果EH涉及大量的狀態,那麼也許你可以建立一個包裝類,把狀態放在堆上,但是它本身被分配爲一個對象。這將允許超載operator()()並獲得所需的語法,同時轉發到底層實現。基本上重構爲Pimpl,以便在您的界面中使用的對象中獲得所需的語法。

+0

我簡化了我的情況。並不是它總是在堆上。這是我通常處理一個傳遞的參考。 – 2014-10-31 16:26:46

0

你可以使用另一個函數作爲包裝,你只需要以稍微不同的方式調用它。

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()); 
1

將堆分配細節封裝在常規類型中並使用常規類型而不是指針通常是一個好主意。

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存儲的指針 「實際」 類。它有轉發到pImpl的方法。

這個類的狀態只是一個指針。它在超出範圍時自動刪除pImplstd::unique_ptr有一個指針(它會代替它)的開銷,除非它在超出範圍時銷燬pImpl對象。

您可以使其僅移動,或手動實現複製構造函數(向_Impl界面添加克隆自身的功能)。

這是一個樣板。

如果您選擇,您可以簡單地將它們寫入常規類型,並讓它們只通過pImpl指針訪問_Impl中的寫入方法。