2012-04-03 72 views
7

我有這樣的代碼:覆蓋和隱藏虛擬功能

class Event{}; 
class CustomEvent:public Event{}; 

class Handler 
{ 
    public: 
     virtual void inform(Event e){} 
}; 

class CustomHandler : public Handler 
{ 
    public: 
    void inform(CustomEvent e){}   

}; 

CustomEvent cEvent; 
Handler* handler = new CustomHandler; 

//this calls Handler::inform(Event), not CustomHandler::(CustomEvent) , as I expected 
handler->inform(cEvent); 

如果我的代碼改成這樣:

class Handler 
{ 
    public: 
     virtual void inform(Event e){} 
     virtual void inform(CustomEvent e){} 

}; 

class CustomHandler : public Handler 
{ 
    public: 
    void inform(CustomEvent e){}   

}; 

CustomEvent cEvent; 
Handler* handler = new CustomHandler; 

//this calls CustomHandler::(CustomEvent) 
handler->inform(cEvent); 

我讀了這個與功能重載連接和隱藏,但仍然沒有按」瞭解此代碼中的行爲。

+3

許多事情都是錯誤的代碼。對於初學者來說,函數參數應該是* references *。 – 2012-04-03 10:12:58

+0

爲什麼要引用? – user152508 2012-04-03 10:20:29

+2

由於(a)切片和(b)不必要的副本。 – ipc 2012-04-03 10:22:39

回答

9

函數重載不工作基礎上,運行類型的參數(這對於你的論點在這裏是CustomHandler*),而是對他們的靜態類型(這裏是Handler*,因爲這就是handler被聲明爲) 。

虛函數允許您根據運行時類型一個對象(您稱之爲函數的對象)進行函數調用。根據多個對象的運行時類型調度調用稱爲多次調度;在這種情況下,我們正在談論double dispatch最常見的情況。如果你想要這種功能,你將不得不實現雙重調度或使用一個庫來爲你做。

Visitor pattern是一個很常見的執行方式;另見Difference betwen Visitor pattern & Double Dispatch

最後,您可以找到訪問者的一個很好的討論,其中包括示例代碼(向下滾動)here

+0

+1你寫了我想要回答的內容。除了我計劃包括一個具體的訪客模式示例。請添加 – 2012-04-03 10:19:39

+0

@ Cheersandhth.-Alf:添加一個鏈接,它應該可以。我不想添加內聯示例(太多的樣板)。 – Jon 2012-04-03 10:28:19