gpt4 book ai didi

c++ - C++中插件的“Best fit”动态类型匹配

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:10:36 25 4
gpt4 key购买 nike

我有一个架构,其中几乎所有内容都是一个插件。该体系结构是图形用户界面的基础,其中每个插件都由“表面”(即用户可以通过其与插件进行交互的UI控件)表示。这些表面也是插件。每当添加新插件时,瘦主机都会自动确定哪个可用表面最适合它。这个问题的主题是如何在C++中实现动态类型匹配。

如您所见,目前,该体系结构是使用C#实现的,很大程度上依赖于反射。但是,我现在正在为C++重新设计整个过程,但是由于C++没有反射(并且由于我是C++的新手),我需要一些有关如何最好地复制没有此功能的信息。

这是目前在C#(简化和伪)中的处理方式:

所有插件都是Plugin类的后代。

每种表面类型均带有“目标插件类型”标记,指示其设计用于的最具体/最深的后代。

最通用的表面是仅处理插件级别的表面(例如,仅显示名称标签)。这样可以确保所有插件至少具有一个可以在屏幕上表示它们的表面,即使它没有提供任何有用的交互方式。

我们将其称为PluginSurface的“基准”表面类型。如果-为了简洁起见(实际上是通过Class Attributes完成的)-我们在表面上使用了一个属性来指示其目标类型,

PluginSurface.TargetType = typeof(Plugin)

除非添加更多特定的表面,否则所有插件都将被分配此通用表面,无论它们在插件继承层次结构中处于何处。

现在,假设我们添加了一个新的插件类型,称为父亲,源自插件:
Father : Plugin

然后我们再添加一些,以创建一些示例层次结构:
Mother : Plugin
Daughter : Father
Son1 : Mother
Son2 : Mother
Grandson : Son1

此时,所有这些都将在屏幕上由通用 PluginSurface表示。因此,我们创建了更多表面来更具体地处理新插件的功能(所有表面均来自PluginSurface):
MotherSurface.TargetType = typeof(Mother)
GrandsonSurface.TargetType = typeof(Grandson)

因此,插件到表面的有效类型匹配应为:
Father -> PluginSurface
Daughter -> PluginSurface
Mother -> MotherSurface
Son1 -> MotherSurface
Son2 -> MotherSurface
Grandson -> GrandsonSurface

好的,这就是我们希望最终得到的映射。本质上,匹配是在主机中作为静态函数实现的,该函数采用插件类型并返回最佳表面的实例:
PluginSurface GetBestFitSurface(Type pluginType)

该函数遍历所有可用表面,并根据提供的 TargetType检查其 pluginType属性。更具体地说,它检查TargetType是否 IsAssignableFrom插件类型。它创建所有正匹配的列表。

然后,它需要缩小此候选列表的最适合范围。为此,我进行了类似的可分配性检查,但是这次在所有候选人的TargetType之间进行检查,对照其他每个候选人进行检查,并为每个候选人记录了可分配其TargetType的其他几个候选人的TargetType。到。可以将TargetType分配(即强制转换)给其他大多数TargetType的候选人是最合适的。

后来发生的事情是,该表面变成了所讨论插件的包装,根据屏幕的紧密程度,将其自身排列在屏幕上以反射(reflect)该插件“理解”的功能。 GrandsonSurface是专门设计用来表示 GrandSon的,因此它将是该插件的完整UI。但是 Son1Son2是“仅”获得 MotherSurface的,因此,它们与 Mother不共有的任何功能都不会包含在其UI表示中(直到建立了更专业的 Son接口(interface),这时才是最好的)适合等)。请注意,这是预期的用途-通常,Mother插件将是抽象的,而针对它的接口(interface)实际上将是Son接口(interface),用于包装Mother的所有子级。因此,单个表面为整个类相似功能的插件提供了UI。

没有反射的支持,如何在C++中最好地做到这一点?

我想面临的挑战是抽出C++的 Type.IsAssignableFrom(Type)的C++类似物,其中两种类型都被动态赋予。.我正在寻找 dynamic_casttypeid的方向,但是到目前为止,我还没有对如何做有一个牢牢的了解。它。有关体系结构,模式或实现细节的任何技巧将不胜感激。

编辑1:我认为我已经解决了这里的主要问题(请参阅下面的我自己的答案,其中包括[非常]粗糙的C++实现),但是可能会有更好的模式。随意撕开它。

编辑2:在下面的后续问题 “Poor Man's Reflection” (AKA bottom-up reflection) in C++中提出了一种改进的模型。

最佳答案

一种选择是在您的Plugin基类中具有一个功能:

virtual std::string id() const { return "Plugin"; }

哪些派生类可以重写,例如,孙子知道其基类是Mother,所以可能编写代码:
override std::string id() const { return "Grandson " + Mother::id(); }

这样,当您在插件上调用 id()时,您会得到类似“孙子母亲插件”的信息。您可以将它扔给 std::stringstream ss(id);,给我们一个 while (ss >> plugin_id),然后在表面容器中寻找使用 plugin_id作为键...。

我认为您不会找到灵活使用 typeiddynamic_cast的方法,因为 typeid不会告诉您基类(*),而且 dynamic_cast必须知道在编译时要测试的类型。我假设您希望能够使用新的插件,并在不编辑代码的情况下更改id-> surface映射的某些文件或其他配置。

(*)如果您准备使用非标准格式,并且符合您的可移植性要求,那么 C++: using typeinfo to test class inheritance提供了一种在运行时获取基类 typeinfo的方法。

关于c++ - C++中插件的“Best fit”动态类型匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20988296/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com