2008-11-24 117 views
6

我的C++框架有按鈕。一個Button派生自Control。所以接受Control的函數可以將Button作爲參數。到現在爲止還挺好。C++模板和繼承

我也有名單< T>。但是,列表<按鈕>並非從List < Control>派生,這意味着接受控件列表的函數不能將Button列表作爲其參數。這很不幸。

也許這是一個愚蠢的問題,但我不知道怎樣才能解決這個:(名單<按鈕>應該從列表<控制>得出,但我不明白的方式來做到這一點「自動」

+0

好的,我的壞。我有指針列表,而不是對象列表。當然,將我的Button * s存儲在Control *列表中可以修復函數調用問題,而且我通常會這樣做,除非我想要一個Button *列表將它們用作Button,而不是Control。 – ggambett 2008-11-24 20:08:13

+0

現在,你有什麼?列表和列表,或列表只?我很困惑。請註明事項:) – 2008-11-24 20:22:39

+0

如果你只有一個列表,並且想要特殊情況下單個元素,如果它們是按鈕類型的,你將被迫使用dynamic_cast mate。 – 2008-11-24 20:23:18

回答

6

我不想告訴你,但是如果你正在使用實例列表來控制,而不是指向Control的指針,你的按鈕無論如何都是垃圾(谷歌「對象切片」)。如果它們是指針列表,則可以按照其他人的建議將list<button*>轉換爲list<control*>,或者從list<button*>複製到新的list<control*>,並將代入該函數。或者將該函數重寫爲模板。

所以,如果你以前有一個叫做DoSomething的功能了一個列表控件作爲參數,你把它改寫爲:

template <class TControl> 
void doSomething(const std::list<TControl*>& myControls) { 
    ... whatever the function is currently doing ... 
} 

void doSomethingElse() { 
    std::list<Button*> buttons; 
    std::list<Control*> controls; 
    doSomething(buttons); 
    doSomething(controls); 
} 
6

如何使用指針?只是有list<Control*>列表,把你喜歡到它的任何控制派生的對象。

2

而不是使用列表<按鈕>,使用列表<控制* >的,這是指向按鈕。這樣,你的功能只有採取一種類型:列表<控制* >。

7

斯特勞斯對這個項目在他的FAQ:

Why can't I assign a vector<Apple*> to a vector<Fruit*>

您可以通過兩種方式解決這個問題:

  • 榜上無名包含指向Control。然後接受List<Control*>
  • 使您的功能成爲模板。你仍然可以使用List<Button>List<Control>,但它更多的是樣板代碼,而且絕大多數時候不需要考慮。

這裏是第二個選擇的代碼。第一種選擇已經由其他答案解釋:

class MyWindow { 
    template<typename T> 
    void doSomething(List<T> & l) { 
     // do something with the list... 
     if(boost::is_same<Control, T>::value) { 
      // special casing Control 

     } else if(boost::is_same<Button, T>::value) { 
      // special casing Button 

     } 

    } 
}; 

要只爲List<derived from Control>限制doSomething,需要一些更多的代碼(尋找enable_if,如果你想知道的)。

請注意,這種代碼(看你有什麼類型)是相當避免。你應該用虛擬功能來處理這些事情。向控制添加功能doSomething,並在按鈕中覆蓋它。

0

一般情況下,C++的方式來寫一個列表執行算法, 序列, ...是提供迭代器作爲參數。

template < class iterator > 
doSomething(iterator beg, iterator end); 

這解決了列表按鈕< *>不從列表衍生<控制*>。 (使用模板列表< T *>也會,但這是讓你的函數通用 - 但不是真的)

根據我的經驗,在迭代器上操作良好的模板化函數可能會很多(太多...)的工作,但它是「C++的方式」...

如果你走這條路線,考慮使用Boost.ConceptCheck。它會讓你的生活變得更輕鬆。