我应该如何用C ++表示一个继承对象树?

时间:2011-07-27 19:08:40

标签: c++ inheritance tree polymorphism

比如说,我有从CPrimus继承的类CSecundusCTertiusCParentis,我想实现一个对象树,其中有叶子(节点?)可以是任何一个派生类的实例,例如:

  • CPrimus
    • CTertius
  • CPrimus
    • CSecundus
      • CTertius
      • CTertius
  • CSecundus
    • CTertius
      • CPrimus
    • CTertius
      • CSecundus
      • CPrimus

在C ++中实现此树的最佳方法是什么,以及可能需要对类进行哪些修改才能支持它?

(*)我会将“最佳”的定义留给社区,无论是“最快”,“最有效”,“最漂亮”,还是您喜欢的任何内容。我个人偏好简单而有效,但如果获得收益,我愿意牺牲简单性。此外,如果您要建议BGL,请尝试举例,或者至少链接到文档或文档的特定部分,以解释如何实现树。

修改

由于这个问题有点过于笼统,我将给出一个潜在的用例。在Linux中,文件系统(通常)将位于裸分区,MD阵列或LVM逻辑卷的顶部。假设我希望我的类表示这些结构并存储关于它们的元数据(设备名称,大小,uuid等等)以供以后检索,并且基类具有一组用于刷新和检索元数据的虚函数。

现在,假设我的系统有一个像这样的磁盘布局:

  • [FS-/引导]
    • [ARR-MD0]
      • [PART-SDA1]
      • [PART-SDB1]
  • [FS- /]
    • [LV-根]
      • [VG-系统]
        • [ARR-MD1]
          • [PART-SDA2]
          • [PART-sdb2]

我如何将其表示为C ++数据结构?

3 个答案:

答案 0 :(得分:3)

啊,是的,多个问题。

<强> 1。容器没有标准的容器,你可以自己滚动,但要完成它需要做很多工作。我找到的最好的东西是Tree Container Library - 免费且记录完备。我没有把它放在重负荷下,但它看起来很“有效”。

<强> 2。多态容器 - 也就是说,不同类型的容器作为元素 - 在C ++中有点痛苦。但是,由于您已经拥有共享基类,因此您有很多选择。

  • [编辑] CParentis中的虚拟方法。
  • static_cast:您将项目存储为CParentis *(或更好,智能指针)。如果对于CParentis *你知道它实际是什么类型,你可以使用static_cast
  • 来强制转换它。
  • dynamic_cast:与上面相同,但dynamic_cast将使用运行时类型信息,您可以“探测”不同类型。然而,根据类层次结构和编译器(游戏开发人员讨厌它,因为在大多数编译器下它无法处理渲染场景的数千个对象),它可能会很慢。
  • boost::any:这是一段来自boost的精彩代码,可让您存储任何类型的代码,并在以后找出要求。像dynamic_cast一样,但不需要共享基类。但是,需要额外的分配 - 可能是数百万个对象的问题。
  • boost::variant:喜欢boost:any,但是对于一组预定义的类型,开销会减少。

如果使用static_cast路由,则需要在类中添加类型标识符(或使用typeof)。但是,切换类型以实现特定处理是代码气味,因为它与所涉及的类的数量/对象的数量严重不同。更好的扩展解决方案是一个共享的抽象基类(当事先知道操作时)或访问者模式(当你需要稍后抛出其他操作时)。

最后,最小的:如果房间里有comp sci专业,则永远不要叫那棵树。 Hel将用他的电子书阅读器砸你的头,解释它是一个有针对性的acyclig图,然后抱怨你打破了他的玩具(至少,这就是我想象我们的comp sci家伙做的,如果他有一本电子书读者...)

答案 1 :(得分:2)

struct Node
{
  CParentis* content;
  std::vector<Node*> children;
};

请注意,没有提及CPrimus 。实际上,这个结构可以包含从CParentis派生的任何内容,包括尚未编写类的实例。

您也可以使用std::whatever_smart_pointer_you_like<...>而不是裸指针,任何容器都是方便的而不是矢量。

如果您可以修改CParentis,则可以为其配备std::vector<CParentis*>并取消Node

答案 2 :(得分:0)

你需要在树中存储CParentis的指针(或更好的智能指针)(当然很明显)。

现在,关于树的实现。首先,检查这个可能的副本:What's a good and stable C++ tree implementation?

然后,这里有一个类似STL的树实现:http://tree.phi-sci.com/