2012-08-11 83 views
4

我有一個模板成員函數的類:麻煩結合GP和OOP概念

class Person 
{ 
    template <typename TItem> 
    void DoSomething(TItem item) 
    { 
    item.Action(); 
    } 
}; 

這讓我傳遞任何物品與行動成員函數,而該人將執行與該項目的行動。所以我可以這樣做:

Person person; 
BaseballBat bat; 
person.DoSomething(bat); 

該結構允許我用任何類型的對象調用函數。但是,如果我想任何類型的對象,我不得不模板類:

template <TItem> 
class Person 
{ 
public: 
    void DoSomething() 
    { 
    this->Item.Action(); 
    } 

    void SetItem(TItem item) 
    { 
    this->Item = item; 
    } 
private: 
    TItem Item; 
}; 

Person<BaseballBat> person; 
BaseballBat bat; 
person.SetItem(&bat); 
person.DoSomething(); 

這是煩人,因爲我不得不重新實例Person類改變的類型目的。

或者,我可以從父類派生的項目:

class Person 
{ 
public: 
    void DoSomething() 
    { 
    this->Item.Action(); 
    } 

    void SetItem(TItem* item) 
    { 
    this->Item = item; 
    } 

private: 
    ParentItem* Item; 
}; 

class ParentItem{}; 

class BaseballBat : public ParentItem 
{} 

Person person; 
BaseballBat bat; 
person.SetItem(&bat); 
person.DoSomething(); 

這是煩人,因爲我必須保持對所有項目的繼承結構(這似乎很「非GP」)。

當我有多層「包含對象的對象」時,問題真的出現了 - 也就是說,我必須將函數模板參數從「頂級」調用傳遞到包含的類:

class BaseballBat 
{ 
    void DoAction(); 
}; 

class Child 
{ 
    template <typename TItem> 
    void DoAction(TItem item) 
    { 
    item.DoAction(); 
    } 
}; 

class Person 
{ 
    Child child; 

    // This is annoying to have to pass the item to the person, who then has to pass it to the child. I'd rather "give" the child an Item, then just be able to call child.DoAction(), where the Person doesn't know anything about the item. 
    template <typename TItem> 
    void PlayWithChild(TItem item) 
    { 
    child.DoAction(item); 
    } 
} 

,可如何函數模板的這兩種想法和存儲對象爲成員的數據正確地搭配任何人對此有何評論? (以上僅僅是一些例子,試圖展示 - 如果它們沒有意義,或者你有更好的例子,那麼我就是所有的耳朵:))。

---------編輯--------- 也許一個更好的例子是我的真實情況的簡化。 我有了一個成員函數的類匹配器:

template<typename TDistanceFunctor, typename TPropagationFunctor> 
void Matcher::Compute(TDistanceFunctor distanceFunctor, TPropagationFunctor propagationFunctor); 

然後,我有另一個類,ImageAlgorithm,使用一個匹配器:

template<typename TMatcher> 
void ImageAlgorithm::Compute(TMatcher matcher) 
{ 
    matcher.Compute(...); // How do I get the DistanceFunctor and the PropagationFunctor here? 
} 

我想打電話給這些東西,如:

Matcher myMatcher; 
.... Setup matcher (how?) ... 
ImageAlgorithm algorithm; 
algorithm.Compute(myMatcher); 

我不知道如何通過ImageAlgorithm對象「穿過」DistanceFunctor和PropagationFunctor,以便它能夠到達ImageAlgor內部的Matcher對象ithm ::計算呼叫。當然,我可以在TDistanceFunctor上模擬匹配器並將TDistanceFunctor存儲爲成員變量,但後來我無法更改匹配器使用不同類型的距離仿函數的距離仿函數。

回答

1

您可以嘗試使用boost::any來容納您的類型變體成員。

從概述:

了boost ::任何類(...)支持任何類型的值和安全的複製檢查該值的提取嚴格針對其類型。

編輯

你說得對與提升存儲的任何函數對象是有問題的是調用。所以我建議另一個解決方案: 使用std :: function(或boost :: function)來包裝你的函子。這樣匹配器就可以保存相關語法的函數對象(例如沒有參數),並且不需要在仿函數類型上進行模板化。

函數對象已經完成了OO(至少在某種意義上)和GP之間的組合。

+0

我從來沒有真正明白boost :: any的用處 - 因爲如果你必須知道從boost :: any中提取對象的類型,那麼你可能只是模板化了一些東西。 – 2012-08-12 13:04:46

+0

boost :: any的思想是接口(接收值)不必知道使用的可能的具體類型。你說得對,這裏沒有與'虛擬'並行的意思(就是說你可以在不關心底層類型的情況下調用一個方法)。你可以有一個類型爲ID的映射來調用函數,但這會很麻煩。我添加了不同的解決方案。 – Asaf 2012-08-14 09:54:28

+0

這意味着我將不得不爲我的匹配器中的每個函數存儲一個std ::函數,雖然對嗎?這看起來很麻煩(比方說Matcher有5個函數,然後Propagator的另一個類似的情況有5個函數,我必須存儲10個std ::函數?) – 2012-08-14 12:59:29