2011-03-27 31 views
4

我在C++中有一個抽象類,有幾個子類。在C++中循環遍歷Abstract類的所有子類是否可能?

是它在某種程度上由宏或模板元編程可以做這樣的事情:

foreach subclass of Base: 
    mymap[subclass::SOME_CONSTANT] = new subclass(); 
+5

不可以。編譯器無法知道您是否在其他翻譯單元中添加了另一個子類。或者鏈接到添加子類的庫。 – Erik 2011-03-27 17:03:05

+2

不,如果你告訴我們你爲什麼要這樣做,我們可以提供一個解決方案。 – fredoverflow 2011-03-27 17:03:21

+0

雖然,AFAIK,這可能無法進行手動註冊(這是首選和安全的方法),但您可以使用[Typelists](http://www.drdobbs.com/generic-programmingtypelists-and-applica/184403813 )來緩解繁瑣的註冊碼。 – 2013-04-06 06:22:59

回答

7

不,你不能。

你想要什麼,顯然是Factory(或者Abstract Factory)。

在C++中,您設置了Factory類和註冊構建器。

class FooFactory 
{ 
public: 
    typedef std::function<Foo*()> Builder; 

    /// returns true if the registration succeeded, false otherwise 
    bool Register(std::string const& key, Builder const& builder) { 
    return map.insert(std::make_pair(key, builder)).second; 
    } 

    /// returns a pointer to a new instance of Foo (or a derived class) 
    /// if the key was found, 0 otherwise 
    Foo* Build(std::string const& key) const { 
    auto it = _map.find(key); 
    if (it == _map.end()) { return 0; } // no such key 
    return (it->second)(); 
    } 

private: 
    std::map<std::string, Builder> _map; 
}; 

您可以創建這個工廠的單,庫負荷,這是非常方便的插件式的建築風格中註冊的派生類:

FooFactory& GetFooFactory() { static FooFactory F; return F; } 

而且你可以準備一個方便的建設者:

template <typename Derived> 
Foo* fooBuilder() { return new Derived(); } 

那麼,人們有望在工廠登記他們的派生類:

static const bool registeredBar = 
    GetFooFactory().Register("Bar", fooBuilder<Bar>); 

注意:工廠應該是單身人士還不是強制性的,儘管它不像這裏那麼邪惡,因爲一旦圖書館的負載結束,它就是不變的。

注意:對於正確的插件架構,您需要使用RAII(而不是bool)來處理庫卸載時的註銷。雖然這很少見。

0

C++不允許迭代類型。也枚舉枚舉成員是不可能的。看到這個:

enum Color 
{ 
    red, 
    green, 
    blue=5, 
    yellow 
}; 

此外,C++編譯器獨立編譯編譯單元。您可以對它進行映像,以便在編譯基類實現時無法知道該類有時會被繼承。