c++ - 保留子类的中央列表,但避免静态实例

标签 c++

我有一个有点讨厌的设置,我正试图找出一个好的方法来彻底检修。

我有一个 class Fractal用几个纯虚函数来工作。每个实例还有一个人类可读的名称。我想构建一个包含所有这些子类的菜单,以便用户可以在它们之间切换 - 但是,由于懒惰,我想避免必须在其源文件中定义每个实例并在另一个文件中再次列出它们。换句话说,我想在运行时动态地构建这个子类列表。

到目前为止,我已经完成(并且正在努力)的是:

  • 定义一个class FractalRegistry这是 std::map<std::string,Fractal*> 的单例封装(其中键是实例名称),
  • 有基地Fractal构造函数在该注册表中按名称注册每个实例(为了完整性,基础 ~Fractal 取消注册它们),
  • 静态实例化每个基类一次(使用它的名称,这是一个构造函数参数)。

所以对于每个新的分形,我都写下这样的东西(释义):

class SomeFractal : public Fractal {
  public:
    SomeFractal(std::string name, std::string desc) : Fractal(name,desc) {}
    virtual void work_function(...) { ... }
}
SomeFractal sf_instance("Some fractal", "This is some fractal or other");

并且实例是由基类构造函数添加到中央列表中的,所以我不需要自己列出它。

但是,这会导致周围有大量静态实例,如果我将此代码移至库中,它们似乎会消失。 (是的,我可以向每个编译单元添加一个可怕的空函数,这样我就可以强制包含它,或者求助于链接器技巧,例如 -Wl,--whole-archive ,但这些似乎也不是正确的答案。)

有没有更好的方法?我想我正在寻找的是一种编写这些 Fractal 实现的方法 - 所有这些实现都具有相同的接口(interface),所以我认为基类的子类是理想的 - 并保留和填充它们的这个中央注册表但不离开我自己是静态实例的地雷。

我错过了什么? 我应该声明,我已经使用 C 多年,但并没有真正了解 C++,所以很可能有一些东西可以完成这项工作……(如果我把它写在C 我会考虑编写一个二阶宏组合,它既声明了一些函数指针,又用它们和分形的名称和描述填充了一个表,但这是一个更 Cish 的事情,而且看起来确实不对对于 C++。)

编辑: 我希望实现的是一种重新安排我的代码的优雅方式,它可以轻松添加新的分形类型并自动填充它们的中央列表,但不会强制程序员创建每个分形的静态实例。

最佳答案

回想一下,静态库是 C++ 之前的技术,因此它们的实现假设未引用的代码是不需要的(事实上,当一个人不玩这个特殊技巧时,它仍然存在于 C++ 中)。

因此,如果您不想探索涉及共享库、插件等的更复杂方法,则需要为每个需要它们的可执行文件明确指定目标文件。这不应该是繁重的:您必须已经有一个进入库的对象的列表,所以不要构建一个库,而是将该列表添加到您的可执行文件的链接器命令行。

关于c++ - 保留子类的中央列表,但避免静态实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6165078/

上一篇:C++ 按需创建

下一篇:c++ - 虚拟继承查询

相关文章:

c++ - CppCoreGuidelines R33 为什么通过引用传递 `unique_ptr`?

c++ - 将带有 "::"的标记作为参数传递给 C/C++ 宏

c++ - 使用带构造函数委托(delegate)的 SFINAE 通过类模板的构造函数一般地应用方法来初始化成员

c++ - 如何使用mpirun为不同的程序使用不同的CPU内核?

c++ - MSI 安装的数据持久化

c++ - 我可以创建具有指定长度但没有初始化的 C++ 字符串/vector 吗?

c++ - sprintf_s() 失败并出现 "debug assertion failed"错误

c++ - 将有符号和无符号十六进制转换为 dec 和 dec 为十六进制 C++

c++ - std::optional 背后的基本原理是什么?

c# - VS2010 中的混合项目解决方案-托管和 native