【问题标题】:Is multiple inheritance acceptable for nodes in a tree?树中的节点可以接受多重继承吗?
【发布时间】:2010-02-11 10:32:43
【问题描述】:

我想知道:

对于一棵树,根可以有多个孩子并且没有 id。所有节点(根节点除外)都有一个 id,叶节点不能有子节点。每个深度必须使用什么类型是固定的。所以叶子总是相同的类型,叶子的父母也是。

由于根和节点可以有子节点,并且只有节点有 id,所以我想知道以下多重继承的使用是否可以接受:

class NodeWithId
{
    private:
        std::string m_id;
};

template<typename T>
class NodeWithChildren
{
    private:
        std::vector<T> m_nodes;
};

class Network: public NodeWithChildren<Subnet>
{
};

class Subnet: public NodeWithChildren<Machine>, 
                     public NodeWithId
{
};

class Machine: public NodeWithChildren<Application>, 
               public NodeWithId
{
};

class Application: public NodeWithId
{
};

或者有没有更好的方法来实现这个?

编辑:

  • 删除了虚拟
  • 更改了类名

【问题讨论】:

  • 为什么要使用虚拟继承?在任何继承路径中都没有共享基类。
  • 我会为所有类型的节点使用一个类,只在根中使用一个虚拟 id,在叶子中使用空子向量
  • 我同意 Manuel 的观点 - 使用 -1 或 0 或其他保留值作为根的 ID,并简化您的设计。

标签: c++


【解决方案1】:

或者有没有更好的方法来实现这个?

恕我直言,您的设计为最适合作为对象实例处理的东西创建了类。在类级别上,我认为不需要区分 Level1 节点和 Level2 节点。

使用简单的设计。问问自己,这种设计是否比拥有单个 Node 类并从 Node 实例(您在运行时创建)中创建树结构的幼稚方法有任何潜在的好处。

【讨论】:

  • 类型安全?如果树中的所有内容都是一个节点,那么您必须动态检查每个节点的类型。
  • @rve: 为什么需要检查Node 的类型?关于您计划在树上执行的操作/算法的一些想法在这里可能会有所帮助。
  • 我想用它来描述一个系统,例如网络中的PC(实际情况类似但更复杂)。所以,根节点就是根。根的孩子是子网,子网的孩子是机器,机器的孩子是应用程序并且是叶子。例如,我想防止将应用程序添加到根目录。如果我获取机器的孩子,我想确定(没有动态类型检查)它们是应用程序。
  • @rve:MachineSubnet 之间的继承位不清楚。在我看来,Node 更像是一个实现细节(是的,你猜对了,这里想到了 pipl-idiom!)。动态类型检查——再次重新思考。还要记住,虚函数通常可以减轻类型检查的痛苦。
  • 你的意思是整个树由 Node 对象和那些 Node 对象组成,然后引用/包含其他一些类,如 Machine、Subnet 等?
【解决方案2】:

你可以用单继承来做到这一点:

class NodeWithId
{
    private:
        std::string m_id;
};

template<typename T>
class NodeWithChildren : public NodeWithId
{
    private:
        std::vector<T> m_nodes;
};

class Root: public NodeWithChildren<Level1Node>
{
};

class Level1Node: public NodeWithChildren<Level2Node>
{
};

class Level2Node: public NodeWithChildren<LeafNode>
{
};

class LeafNode: public NodeWithId
{
};

只有在您可以拥有一个没有 ID 的 NodeWithChildren 的情况下,您才需要多重继承。在您上面的设计中,每个 NodeWithChildren 也有一个 NodeWithId,因此您不妨从 NodeWithId 派生 NodeWithChildren 并完全绕过任何潜在的多重继承问题。

对我来说似乎是一个“更好”的设计......

【讨论】:

  • 但是我必须给根一个虚拟 id。
【解决方案3】:

首先,不需要虚拟继承,根据你贴的示例代码,没有'dreaded diamond'

但我根本不明白你的设计,没有任何代表你的树的通用基类,你为什么要使用继承?看起来一切都可以使用合成来实现。

这仅仅是为这个问题制作的层次结构的精简版本吗?

【讨论】:

  • 嗯,一些节点可以有子节点,管理这个子节点列表的代码可以在基类中,因为它对于所有节点都是相同的(除了离开节点)。是的,您对虚拟继承是正确的。你能举例说明如何通过组合来做到这一点吗?
【解决方案4】:

你的表现将难以忍受,你的代码令人难以置信的复杂。

首先,您为每个节点使用一个模板,其中包含一个向量。

仅矢量就会大大减慢速度。必须强制转换会使您的遍历代码非常非常慢,并且代码本身很难被其他人理解。

另外,既然你有不同的类,向量如何处理呢?回答,不能。这意味着它必须是指向基类的指针向量。然后你必须在运行时弄清楚什么是正确的类型才能充分利用它们。

如果这增加了某种好处,那么它对于某些用途可能是值得的,但这与你想要从树这样的结构中获得的效果相反,它应该尽可能简单地使用和理解并具有尽可能少的内存分配和理想的良好性能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-14
    • 2023-03-06
    • 2010-10-09
    • 2015-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多