你可以让所有的类在某种集合中自行注册。这里有一个骨架的方法:
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