你可以讓所有的類在某種集合中自行註冊。這裏有一個骨架的方法:
Base.hpp:
#include <memory>
#include <unordered_map>
#include <string>
struct Base
{
virtual ~Base() = default;
using create_f = std::unique_ptr<Base>();
static void registrate(std::string const & name, create_f * fp)
{
registry()[name] = fp;
}
static std::unique_ptr<Base> instantiate(std::string const & name)
{
auto it = registry().find(name);
return it == registry().end() ? nullptr : (it->second)();
}
template <typename D>
struct Registrar
{
explicit Registrar(std::string const & name)
{
Base::registrate(name, &D::create);
}
// make non-copyable, etc.
};
private:
static std::unordered_map<std::string, create_f *> & registry();
};
Base.cpp:
#include "Base.hpp"
std::unordered_map<std::string, Base::create_f *> & Base::registry()
{
static std::unordered_map<std::string, Base::create_f *> impl;
return impl;
}
我們在客戶端使用:
派生。 hpp:
#include "Base.hpp"
struct Derived : Base
{
static std::unique_ptr<Base> create() { return std::make_unique<Derived>(); }
// ...
};
Derived.cpp:
#include "Derived.hpp"
namespace
{
Base::Registrar<Derived> registrar("MyClass");
}
的Base::Registrar<Derived>
的構造函數的名稱"MyClass"
下注冊類Derived
的照顧。您可以通過動態創建的Derived
實例:
std::unique_ptr<Base> p = Base::instantiate("MyClass");
的代碼可以/應該通過檢測重複註冊,打印的可用類的列表等。注意我們如何避免我做實際的任何靜態初始化順序的問題得到改善註冊表映射對象是一個塊靜態對象,它保證在第一次使用之前被初始化,並且僅在其最後一次使用之後才被銷燬。
正在生成一個頭可接受的解決方案? – Arpegius