我正在尝试编写一个在运行时动态加载其扩展的应用程序。我使用 Boost 预处理器库编写了一个预处理器函数,给定一个名称列表,为每个名称声明一个类(并使它们成为某个 AbstractPlugin 类的子类),然后声明一个包含这些类的 Boost MPL 序列。然后我写了一个类,如果它可以转换为该 MPL 序列中的任何类型,它会尝试指向 AbstractPlugin 的指针。 这里的问题是我的预处理器函数需要我想要创建和加载的所有扩展的完整列表。是否有某种技术可以让我在单独的文件中注册每个扩展?
更新:
我认为,我对情况的解释过于模糊,所以我决定更具体一些。
我想定义一个扩展类型的集合。对于每种扩展类型,可以有任意数量的扩展。在运行时,程序加载外部库,解析入口点函数,调用它,结果得到一个指针。然后它尝试将该指针转换为所有已注册的扩展类型(使用 dynamic_cast
,因此扩展类型的类都继承自某个多态基类)。如果对某些扩展类型的转换成功,则转换后的指针将用于调用该扩展类型的特殊处理程序。
扩展类型的数量在编译时是已知的(而显然,扩展的数量是无限的)。使用我的方法,加载程序类使用此知识来检查是否存在每个扩展类型的处理程序(如果不存在,则程序不会编译)。此外,我的方法不会强制扩展类型的类知道加载程序的任何信息(因此很容易修改加载程序)。但是如果每个扩展类型都自己注册会更方便。
最佳答案
您可以让您的所有类在某种集合中自行注册。这是一个框架方法:
基础.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();
};
基础.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;
}
现在在客户端中使用它:
Derived.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>
的构造函数负责注册类(class) Derived
名下"MyClass"
.您可以创建 Derived
的实例动态通过:
std::unique_ptr<Base> p = Base::instantiate("MyClass");
可以/应该通过检测重复注册、打印可用类列表等来改进代码。请注意我们如何避免任何静态初始化排序问题,我将实际的注册表映射对象设为 block 静态对象,这保证了在首次使用前进行初始化,因此仅在最后一次使用后销毁。
关于c++ - 注册一个 C++ 类,以便稍后一个函数可以遍历所有已注册的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11175379/