【问题标题】:How to handle mixed collections of objects in C++如何在 C++ 中处理对象的混合集合
【发布时间】:2018-02-26 13:09:05
【问题描述】:

我正在研究基于 C++ 分层树的类设计,具有两种对象类型,A 和 B。

A 类对象可以有任意数量的 A 或 B 类型的子对象,但它们必须按单一顺序存储。 B 类对象可能没有任何子对象。

我的问题是关于在 C++ 中处理混合类型集合的最佳 OO 实践。

我可以看到的一个解决方案是创建一个基类,A 和 B 都从该基类派生,并让 A 持有 vector<Base*> children。这似乎是一个很好的解决方案,除了下线更有可能是一些动态转换来确定子类型,我被告知这可能是代码设计不佳的症状。

另一个选项是让 A 类保存一个单独的 A 和 B 子级列表,以及一个表示该子级在组合子级列表中的位置的值。这似乎是一个更有问题的解决方案,因为当插入、删除或重新排列项目时,必须手动维护位置值。

第三种选择是将 A 类和 B 类的功能整合到一个类中,并有一个标志来说明如何解释对象。

这些是我解决这个问题的唯一选择吗?我是否错过了一些更优雅的解决方案,或者从错误的方向接近它?我已经看到 Boost 有一些用于异构集合的选项,但不幸的是,在这个项目中使用 Boost 不是一个选项。

编辑:我将尝试用更多细节来描述真实案例

A 类对象定义集合。它们保存字符串路径或模式,以定义一组对象(来自用户创建的池)。子集合定义了更多的子集。

B 类对象是覆盖对象。它们描述了要应用于由父 A 对象定义的对象集的操作。

集合和集合的顺序决定了覆盖的应用顺序。

我发现需要向下转型的点是在评估阶段,我在树中迭代以整理和应用覆盖 - 我需要知道如何处理树中的每个项目以及是否要查找位置或覆盖数据。从我收到的 cmets 看来,我应该能够通过真正的 OO 设计来完成我所需要的,所以在我模棱两可地说不然之前,我会再试一次。

【问题讨论】:

  • 为什么在第一个解决方案中需要向下转型?你需要解决什么问题,你不能通过virtual 函数(和多态性)解决?
  • 第一种解决方案不能在 A 和 B 中都实现 GetType 方法以避免动态转换吗?
  • @UnholySheep,如果每个类都有一些独特的成员函数,我怎样才能在不向下转换的情况下从基类指针访问它们?
  • @KillzoneKid 你的意思是像从 GetType 检查枚举,然后根据结果进行静态转换?这比动态演员表更好吗?
  • 为什么您的子类具有您需要直接访问的独特功能?我发现您的示例过于抽象,无法说明AB 的真正要求(和用法)是什么。尽管应尽可能避免使用dynamic_cast,但在某些情况下是必要的。

标签: c++ class oop parent-child hierarchical-data


【解决方案1】:

对于 C++17,您可以使用 std::variant

struct B {
// ...
};

struct A {
std::vector<std::variant<A, B> > children;
// ...
};

【讨论】:

  • 感谢 Olaf,很高兴知道这一点,尽管我们还不能使用 C++11。希望这种情况很快就会改变,但我必须在那之前做到。
【解决方案2】:

您提出的解决方案都与 OO 或多态性或任何此类流行语无关。 (并不是说有任何固有的问题)。

OO 解决方案将完全依赖Base 中的虚拟函数 来执行特定于每个特定派生类的工作。不多也不少。

【讨论】:

  • 那么您是否建议在基类中使用特定于每个子类(甚至仅由其实现)的虚函数?还是应该基类函数始终是通用的,但返回的数据根据​​它们的类型(由某些 GetType 方法提供)进行不同的解释?
  • @Joe 您在问“如何编写面向对象的软件”。这太宽泛了。但是不,没有GetType。每个特定功能仅在特定派生类中实现。你的基本函数可能是纯虚拟的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-05
  • 2018-08-27
  • 2019-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多