2012-01-05 57 views
0

在我的節目,我覺得我想要一個UserClass如何讓一個類包含不同的類類型並調用這些對象的成員?

  1. 是可以容納異質類型
  2. 可以撥打舉行的對象的成員函數的容器的情況。

保存的類型集在編譯時是有限的和已知的。實際上,所有的類型只是不同template專業化。

此代碼說明了情況:

class ArrayBase { /*etc.*/ }; // definition not changeable 

template <class T> 
class TypedArray : public ArrayBase // definition not changeable 
{ 
/*more functionality needed by SpecializedArray.*/ 
} 

template<class T> 
class SpecializedArray : public TypedArray<T> 
{ 
public: 
void newFunctionalityMember() { /*etc.*/ }; 
}; 

class UserClass 
{ 
    addArray(arrayElmentTypeEnum_t t) 
    { 
     switch(t) { 
     case float_id: 
      _elementArrays.push_back(new SpecializedArray<float>()); 
      break; 
     case double_id: 
      _elementArrays.push_back(new SpecializedArray<double>()); 
      break; 
     default: 
      break; 
    } 

    void doSomethingWithASpecializedArray(int num) 
    { 
     // using _elementArrays[num], call the correct newFunctionalityMember() 

    } 

    private: 
     std::vetor<storagePtr_t> _elementArrays; 
} 

沒有一些懇求,我沒有靈活地改變ArrayBaseTypedArray。 我已經離開storagePtr_t類型undefined,因爲它應該是什麼類型是我的問題的關鍵部分。

我可以想到一個解決方案,如下圖所示。但是多麼痛苦!這是在UserClass中有很多我需要訪問元素成員的代碼。 有沒有更好的方法?

助推庫是公平的遊戲。

我的技術:

storagePtr_tArrayBase*arrayElmentTypeEnum_t將是一個std::type_info*

UserClass::doSomethingWithASpecializedArray(int num) 
{ 
// these two both uniquely identified by num. 
storagePtr_t * bptr = _elementArrays[num]; 
arrayElmentTypeEnum_t typekey = ... 

    if  (typekey == &typeid(SpecializedArray<float>)) { 
     D<float> * dptr = static_cast<SpecializedArray<float>*>(bptr); 
     dptr->newFunctionalityMember(); 
    } else if (typekey == &typeid(SpecializedArray<double>)) { 
     D<float> * dptr = static_cast<SpecializedArray<double>*>(bptr); 
     dptr->newFunctionalityMember(); 
    } else if (typekey == &typeid(SpecializedArray<int>)) { 
     D<float> * dptr = static_cast<SpecializedArray<int>*>(bptr); 
     dptr->newFunctionalityMember(); 
    } 
} 
+0

不幸的是,我發現我的前面[問題](http://stackoverflow.com/questions/8736923/cast-base-class-pointer-to - 基於指針的幾種可能派生類型指針)沒有包含足夠詳細的案例來清除有用的解決方案。 – NoahR 2012-01-05 06:07:30

+1

爲什麼你不能'UserClass'也是'template'?這會讓你免於混亂,不是嗎? – iammilind 2012-01-05 06:36:51

回答

2

你可以引入新的基類,定義要調用的接口:

class SpecializedArrayBase { 
public: 
    virtual ~SpecializedArrayBase() {} 
    virtual void newFunctionalityMember() = 0; 
}; 

然後派生從這個基地的數組類型:

template<class T> 
class SpecializedArray : public TypedArray<T>, public SpecializedArrayBase 
{ 
public: 
    void newFunctionalityMember() { /*etc.*/ }; 
}; 

然後,您可以在您的載體存儲對象由新的基本類型SpecializedArrayBase

typedef SpecializedArrayBase* storagePtr_t; 

由於基類定義要調用的功能,你可以避免所有鑄件和調用它通過基指針:

void doSomethingWithASpecializedArray(int num) 
{ 
    for (size_t i = 0; i < _elementArrays.size(); ++i) { 
     _elementArrays[i]->newFunctionalityMember(); 
    } 
} 
+0

謝謝@DRH!這很好。我沒有考慮從兩個班繼承。 這可能是值得指出的是'SpecializedArrayBase'應該有一個虛析構函數,或'UserClass'析構函數應該是關於確保了'SpecializedArray'析構函數被稱爲非常明確的。 – NoahR 2012-01-05 07:41:29

+0

謝謝@NoahR,我在示例中添加了一個虛擬dtor。 – DRH 2012-01-05 14:32:30

相關問題