2010-11-09 64 views
1

我偶然發現了一個問題,這個問題一眼就可以輕鬆實現,但仔細研究似乎並不存在。當所有類型都不知道時,函數從基類中重載

我有我的計劃項目,我需要與許多類型的工作,所以我決定在一個通用的,可擴展的方式來處理這些:

class ItemBase 
{ 
public: 
virtual ~ItemBase() = 0 {} 
    // pure virtual class, some extra members 
}; 

template<typename T> 
class ItemT : public ItemBase 
{ 
public: 
ItemT(const T &data) : m_Data(data) {} 

T m_Data; 
}; 

我現在可以存儲在一個集合中的任何類型:

std::vector<ItemBase*> items; 

這很好。現在我有我想保持從這個類單獨的GUI組件,所以我想生成取決於類型的GUI組件:

GuiComponent* BuildComponent(ItemT<int> &item) 
{ 
    // do whatever based on this type, the int is needed 
} 

GuiComponent* BuildComponent(ItemT<double> &item) 
{ 
    // do whatever based on this type, the double is needed 
} 

這幾乎是美麗的編碼。不幸的是它不起作用。由於此程序顯示:

std::vector<ItemBase*> m_Items; 
m_Items.push_back(new ItemT<int>(3)); 
m_Items.push_back(new ItemT<double>(2.0)); 
BuildComponent(*m_Items[0]); 

因爲m_Items [0]的類型爲ItemBase *。

那麼我該如何解決這個問題呢?什麼設計模式或模板欺騙可以幫助我在這裏?

+0

您是否正在編譯時錯誤?運行時錯誤? – 2010-11-09 19:38:15

+0

編譯時間「沒有重載可以轉換所有參數類型」 – DanDan 2010-11-09 19:40:42

+0

好,首先,您的抽象聲明是不正確的。抽象聲明之後不應該有{}。 {}是派生類實現的。這也意味着你的ItemT類需要實現基類的析構函數。 – 2010-11-09 19:46:12

回答

4

簡單的答案是:在ItemBase中添加虛擬buildComponent方法。但是,由於要保持GUI組件分離,我建議使用Visitor模式。

一個非常簡單的實現將包括:

  • 添加在ItemBase
  • 實現在每一個派生類此方法的單個accept(AbstractVisitorType &)虛擬方法通過調用visitor.visit(*this),這意味着AbstractVisitorType必須提供一個虛擬visit方法可以調用每個具體類型(參見下面的註釋)
  • 提供此訪問者的具體實現,它將在其每個中實例化適當的GUI對象基於參數類型的過載。

然而要注意的訪問者模式只適合於相當穩定的類層次結構:使用ItemT模板的新實例將要求遊客一邊維護處理這種新型的(但你最初的想法有同樣的問題)。

現代C++設計(Andrei Alexandrescu)的第10章是關於訪問者模式的精彩閱讀。

+0

是的,我明白我需要同時維護兩個班級的女同志。你有不同的想法可以使用嗎? – DanDan 2010-11-09 19:52:21

+0

訪客模式幾乎完美。不幸的是,我必須通過在頭文件中包含所有這些可用的函數,讓這個類知道它將如何使用。虛擬函數不能被模板化是一種恥辱。 – DanDan 2010-11-09 20:27:56

+0

其實這個工程! – DanDan 2010-11-09 20:33:30

相關問題