2009-07-06 40 views
2

是否有可能控制從配置中創建不同的類?是否可以創建可通過配置控制的不同類?

說,我有一個函數,這是否是硬編碼:

BaseClass* getClassObject(int type) 
{ 
    switch (type) 
    { 
    case 1: 
     return new DerivedClass1(); 
    case 2: 
     return new DerivedClass2(); 
    default: 
     return 0; 
    } 
} 

是否有可能控制轉移到某些類型的數據結構,使得用戶只需要填寫數據結構來控制函數的行爲?

+1

也許你可以澄清一點問題。你的switch語句有什麼問題?在編譯時需要知道類型的事實?你想傳遞一個不同於整數的東西嗎(比如說一個帶類名的字符串)? – 2009-07-06 11:04:13

回答

0

我不是C++大師 - 我來自Delphi/C#背景。在Delphi或C#中,我會使用反射來動態創建可能的類的列表,然後選擇在某個配置文件中配置的類。但是,我不確定在C++中這是否可行?

+0

C++不支持你正在談論的那種反射。 – 2009-07-06 11:02:07

+0

好吧,那真是太遺憾了;-)把我的答案從有用的答覆列表中刪除,然後...... – 2009-07-06 11:12:30

+0

或者,您可以刪除它,然後開始標記; – 2009-07-06 11:23:57

1

在C++中,編譯時必須知道所有類型的名稱。您不能允許用戶在運行時發現類。但是,您發佈的函數可以工作 - 配置文件將包含一個整數,指示是否要創建DerivedClass1或DerivedClass2。這是讀取和用於執行開關。

2

正如Neil在C++中提到的那樣,你不能在運行時發現類。

我可能沒有正確理解你的問題,但是如果你想讓一個函數/對象對用戶提供的數據有不同的表現,你可以根據你的需要嘗試下面的任何一種。

1]在你的代碼中提到片斷您可以使用開關或條件語句(爲用戶提供的數據不同的行爲函數)來創建所需的

2]可以使用工廠模式對象類型(以創建不同的對象作爲每個用戶提供的數據,該對象可以具有一個共同的基類爲可更換的代碼來生成不同的行爲)

3]可以使用梳一個創作者函數 b)繼承和接口 c)和動態庫加載 在運行時創建並加載適當類型的對象。 (這是在運行時按照給定的用戶數據僅加載特定對象或函數)

1

從問題中提供的有限信息中,您可能需要考慮閱讀和/或考慮使用C++依賴注入容器。

這對您的要求可能有點沉重,但從問題很難說清楚。僅供參考,依賴注入(http://martinfowler.com/articles/injection.html)是Martin Fowler創造的一個術語,是一種更具體的控制反轉(我會讓你進一步研究這兩個主題)。

我個人曾與Castle Windsor合作過,它是一個C#/ .NET依賴注入容器,它允許通過配置文件運行時構建請求對象。

維基百科上有一個C++依賴注入容器的列表(http://en.wikipedia.org/wiki/Dependency_injection#Existing_frameworks) - 我做了任何C++已經有幾年了,所以我不能告訴你更多關於它們的信息。

1

另一種替代方法是使用原型模式,其中BaseClass的部分接口是clone()函數。然後你創建一個原型實例的數組,然後調用clone來獲得你的新對象。如果要創建值不同的實例以及僅行爲不同的實例,並且通常比創建工廠方法的工作量少,這很有用。

class BaseClass 
{ 
public: 
    virtual BaseClass* clone() const = 0; 
    virtual ~BaseClass() { } 
    virtual void write() const = 0; 
}; 

template <class C> 
class Cloneable : public BaseClass 
{ 
public: 
    virtual BaseClass* clone() const { 
     return new C (*static_cast<const C*> (this)); 
    } 
}; 

class TypeA : public Cloneable<TypeA> 
{ 
    int value; 

public: 
    TypeA (int value) : value (value) { } 

    virtual void write() const { 
     std::cout << "TypeA (" << value << ") @ " << (void*) this << std::endl; 
    } 
}; 

class TypeB : public Cloneable<TypeB> 
{ 
public: 
    TypeB() { } 

    virtual void write() const { 
     std::cout << "TypeB @ " << (void*) this << std::endl; 
    } 
}; 



int main (int argc, char* argv[]) 
{ 
    std::vector<BaseClass*> prototypes; 

    prototypes.push_back (new TypeA (1)); 
    prototypes.push_back (new TypeA (2)); 
    prototypes.push_back (new TypeB); 

    // create some objects 
    std::vector<BaseClass*> instances; 

    for (size_t i (0); i < 8; ++i) 
     instances.push_back (prototypes [ i % 3 ] -> clone()); 

    for (size_t i (0); i < 8; ++i) 
     instances[ i ] -> write(); 

    // todo: delete everything 
} 
相關問題