2011-11-25 42 views
5

可能重複:
Is there a way to instantiate objects from a string holding their class name?如何實例化一個只知道它的名字的對象?

在C++中,我希望有我的用戶輸入的對象類型名稱在運行時創建,並且,根據不同的字符串,我得到從他們那裏,程序將實例化正確的對象(簡而言之,我實現了工廠方法模式)。但是,如果程序必須支持新的對象類型,則不允許修改現有代碼。

所以有可能刪除所有if ... else if ... else if ...方法中的東西,並且仍然讓我的程序實例化特定產品類型的正確對象(超出了許多,只有在編譯時才知道)?

我在周圍尋找這個鏈接:Is there a way to instantiate objects from a string holding their class name?,它似乎是我想要的,但我根本無法理解代碼。

任何幫助將非常感激。

+0

@CharlesB你不需要反思,你可以使用工廠。 –

+1

@LuchianGrigore:工廠是一種設計模式,反射是一種語言特徵。如果你想要一個沒有if..else..else的工廠,你需要一個有反射的語言,或者一個二進制插件架構,就像在Alessandro的回答中一樣 – CharlesB

回答

5

如果所有必需的類都是由一些常見的基類派生這隻會工作,你一般會被限制使用的基本接口(雖然你可以工作圍繞這一點,一些額外的努力)。這裏有一個方法:

// Immutable core code: 

#include <map> 
#include <string> 

class Base 
{ 
    typedef Base * (*crfnptr)(const std::string &); 
    typedef std::map<std::string, crfnptr> CreatorMap; 

    static CreatorMap creators; 

public: 
    virtual ~Base() { } 
    Base * clone() const { return new Base(*this); } 

    static Base * create_from_string(std::string name) 
    { 
    CreatorMap::const_iterator it = creators.find(name); 
    return it == creators.end() ? NULL : it->first(); 
    } 

    static void register(std::string name, crfnptr f) 
    { 
    creators[name] = f; 
    } 
}; 

現在你可以從你的新代碼添加新的派生類:

// your code: 

#include "immutable_core.hpp" 

class Foo : public Base 
{ 
public: 
    Foo * clone() const { return new Foo(*this); } 
    static Foo * create() { return new Foo; } 
}; 

Base::register("Foo", &Foo::create); 

要創建一個類,你只需撥打Base * p = Base::create_from_string("Foo");

+0

這裏需要'clone()'函數嗎? 我不確定將它們去除是否是個好主意。 – Daan

+0

@Daan:你說得對,他們對於工廠本身並不是必需的,但是在你不知道對象的派生類型最多的情況下,他們扮演着複製構造器的角色,所以他們在主題上是相關的。 –

+0

所以,如果我理解正確,我需要他們毫無疑問從'Base *'轉換爲'Derived *'? – Daan

2

你可以這樣做,實現像插件系統。我在Linux中使用dlopen實現了這個功能。該程序不需要修改,但只需將新類添加爲將在運行時加載的動態庫。

你可以從這裏開始瞭解更多信息:C++ dlopen mini HOWTO

相關問題