2010-07-19 140 views
2

我有一些類,所有的接口都完全相同。這個接口定義了一些方法,其中一些是模板化的(類本身可能會或可能不會)。使用相同的接口傳遞不同類型的對象

所以界面看起來像這樣

class MyClass 
{ 
public: 
    void Func1(); 

    template <typename T> 
    void Func2(T param); 
}; 

我有一些它需要符合本接口,但要避免必須在編譯時知道確切執行各種對象的功能。

顯然,默認的C++解決方案應該有一個基類型,所有這些類派生並傳遞一個指針,並使用多態性完成所有工作。

問題是模板化的成員函數不能是虛擬的,所以這個方法不能使用。我也想避免改變當前接口集合,因爲它們有很多,其中一些定義在我的項目範圍之外。

另一種解決方案是對使用這些對象的函數進行模板化,使它們專注於正確的類型。這可能是一個解決方案,但由於遺留需求,大量功能模板可能不可行(這是我不能做任何事情的事情,因爲客戶端代碼不是我負責的東西)。

我最初的想法是提供某種類型的載體類,它是類型中性的,並且在效果中包含了這裏的通用接口,並且有一個基類接口類來傳遞內部類型。

東西沿着

class MyInterface 
{ 
public: 
virtual void Func1() = 0; 
}; 

template <typename T> 
class MyImplementation 
{ 
public: 
    virtual void Func1() 
    { 
    m_impl->Func1(); 
    } 

private: 
    T* m_impl; 
}; 

線但同樣的模板成員函數似乎阻止這種做法。

我看了一下boost :: any和boost :: function類,我認爲它們可以提供某種解決方案,但它們似乎並沒有給我正確的答案。

那麼,有沒有人有任何建議或解決如何使這成爲可能,如果的確如此?就我個人而言,我傾向於對需要這些對象的各種功能進行模板化 - 因爲這是功能模板提供的 - 但認爲它值得首先進行調查。

在此先感謝

+0

你真的想解決什麼問題? – 2010-07-19 14:45:20

+0

我有很多函數採用符合這個接口的各種對象,但是想避免在編譯時需要知道確切的實現。 – 2010-07-19 14:57:40

+0

您可以嘗試檢查有關您的主要問題的問題:如何解決虛擬模板功能問題。我知道我之前看到過這個問題。我不確定你是否會在那裏找到你的解決方案,但這將是一個好的開始。 – n1ckp 2010-07-19 15:09:05

回答

2

對於我來說,不完全清楚的是你如何解決參數T到Func2,你是否也需要某種動態調度,或者在編譯時在調用站點是否已知?

在前一種情況下,它聽起來像多種方法。在後者中,接口思想如何變化:

#include <iostream> 

template<class T> struct generic_delegate 
{ 
    virtual void call(T param) = 0; 
}; 

template<class U, class T> class fn_delegate : public generic_delegate<T> 
{ 
    U* obj; 
    void (U::*fn)(T); 

public: 
    fn_delegate(U* o, void (U::*f)(T)) : 
    obj(o), fn(f) 
    {} 

    virtual void call(T param) 
    { 
    (obj->*fn)(param); 
    } 
}; 


class A 
{ 
public: 
    template<class T> void fn(T param) 
    { 
    std::cout << "A: " << param << std::endl; 
    } 
}; 

class B 
{ 
public: 
    template<class T> void fn(T param) 
    { 
    std::cout << "B: " << param << std::endl; 
    } 
}; 


template<class T, class U> generic_delegate<T>* fn_deleg(U* o) 
{ 
    return new fn_delegate<U, T>(o, &U::template fn<T>); 
} 


int main() 
{ 
    A a; 
    B b; 

    generic_delegate<int>* i = fn_deleg<int>(&a); 
    generic_delegate<int>* j = fn_deleg<int>(&b); 

    i->call(4); 
    j->call(5); 
} 

很明顯,你要傳遞的東西是泛型的委託指針。

1

如果你使用,你需要知道的模板你正在使用的類型編譯時間。這就是模板的本質(模板看起來像是在運行時是動態的代碼,但實際上它只是速記,告訴編譯器編譯哪些版本的函數並將其包含在目標代碼中)。最好的情況下西安娜是這樣的:

template <class T> 
void DoSomethingWithMyInterface(MyInterface<T> X) 
{ 
    //do something 
} 

... 

switch (MyObject.GetTypeCode()) 
{ 
case TYPE1: DoSomethingWithMyInterface<type1>(MyObject); break; 
case TYPE2: DoSomethingWithMyInterface<type2>(MyObject); break; 
case TYPE3: DoSomethingWithMyInterface<type3>(MyObject); break; 
case TYPE4: DoSomethingWithMyInterface<type4>(MyObject); break; 
} 

我實際上使用這種情況很多。我編寫模板化的C++代碼,爲動態類型語言進行處理。這意味着頂級語言直到運行時才知道數據類型,但我需要在編譯時瞭解它們。所以我創建了這個「TypeSwitch」(我實際上有一個花哨的可重用的)。它在運行時查看數據類型,然後找出哪些已編譯的模板函數可以運行。

注意 - 這需要我知道所有類型,我會支持之前(和我這樣做)和switch語句實際上導致編譯器生成所有可執行的代碼。然後在運行時選擇正確的一個。

+0

這是一個有趣的解決方案,我認爲可以解決這種情況下的問題。客戶端正在處理各種對象的一小部分,不需要大量的switch語句。 – 2010-07-19 15:25:55

相關問題