保留一个中间的子类列表,但避免静态实例(Keep a central list of subclasses but avoiding static instances)

编程入门 行业动态 更新时间:2024-10-06 22:20:45
保留一个中间的子类列表,但避免静态实例(Keep a central list of subclasses but avoiding static instances)

我有一个稍微讨厌的设置,我试图找出一个好方法进行检修。

我有一个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实现的方法 - 所有这些实现都有相同的接口,所以我认为基类的子类将是理想的 - 并且保留并填充它们的中央注册表,但不会离开我自己是静态实例的地雷。

我错过了什么? 我应该说,我已经和C一起工作了很多年,但并没有真正拥有C ++的禅宗,所以很可能会有这样的工作能够做到让我面对我的工作......(如果我是这样写的C我会考虑编写一个二阶宏组合,它既声明了一些函数指针,又用它们和分形的名称和描述填充了一张表,但这是一个更加Cish的事情,它看起来确实不正确对于C ++。)

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

I have a slightly nasty setup which I am trying to figure out a good way to overhaul.

I have a class Fractal with a couple of pure virtual functions to do work. Each instance also has a human-readable name. I want to build a menu of all these subclasses so the user can switch between them - but, being lazy, I want to avoid having to both define each instance in its source file and list them all again in another. In other words, I want to build up this list of subclasses dynamically at runtime.

What I have done (and have working) so far is:

define a class FractalRegistry which is a singleton encapsulation of a std::map<std::string,Fractal*> (where the keys are the instance names), have the base Fractal constructor register each instance by name with that registry (and for completeness the base ~Fractal deregister them), statically instantiate each base class once (with its name, which is a constructor argument).

So for each new fractal I write something like this (paraphrased):

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");

and the instance is added to the central list by the base class constructor, so I don't need to list it myself.

However, this leads to having a load of static instances lying around, which appear to vanish if I move this code into a library. (Yes I can add a horrid empty function to each compile unit so I can force its inclusion, or resort to linker trickery such as -Wl,--whole-archive, but these don't seem like the right answer either.)

Is there a better way? What I guess I'm looking for is a way to write these Fractal implementations - all of which have the same interface, so I thought subclasses of a base class would be ideal - and to keep and populate this central registry of them but without leaving myself the landmine of static instances.

What have I missed? I should state that I've been working with C for years but don't really have the zen of C++, so there might well be something that would do the job staring me in the face... (If I was writing this in C I'd think about writing a second-order macro composite which both declared some function pointers and populated a table with them and the fractals' names and descriptions, but that's an even more Cish thing to do and it really doesn't seem right for C++.)

Edit: What I am hoping to achieve is an elegant way of rearranging my code which makes it easy to add new fractal types and automatically populates a central list of them, but doesn't force the programmer to create a static instance of every fractal.

最满意答案

回想一下,静态库是pre-C ++技术,因此它们的实现假定未引用的代码是不需要的是不合理的(当人们不玩这个特殊技巧时,实际上它仍然是C ++)。

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

Recall that static libraries are pre-C++ technology, so it’s not unreasonable for their implementation to assume that unreferenced code is unwanted (as indeed it still is in C++ when one is not playing this particular trick).

As such you need to specify the object files explicitly for each executable that needs them, assuming you don’t want to explore more complicated approaches involving shared libraries, plugins, and so on. This should not be onerous: you must already have a list of the objects that go into the library, so instead of building a library add that list to the linker command line of your executables.

更多推荐

本文发布于:2023-08-07 16:22:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1465217.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:子类   静态   实例   列表   central

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!