【问题标题】:C++ n-arry tree with different elements具有不同元素的 C++ n-ary 树
【发布时间】:2021-12-30 15:14:05
【问题描述】:

我想从一个文档构建一个 n-arry 树。为此,我有 3 种不同类型的树元素:

  • 结构节点
    • 有名字
    • 可以包含其他节点
    • 深度
  • 元素节点(树的叶子)
    • 有钥匙
    • 有一个价值
    • 深度
  • 元素模板节点(树的叶子)
    • 有一个占位符,应该稍后在程序中解决
    • 深度

此刻我在想这样的事情:


class Node {
    public:
        Node(int depth);
        int depth() const;
    private:
        int depth_;
};

class StructNode : public Node {
    ...
    private:
        std::vector<std::unique_ptr<Node>> children;
};

class ElementNode : public Node {
...
};

class ElementTemplateNode : public Node {
...
};

树将在启动时从文件生成,并重复使用以创建如下输出字符串:

Structname:
   key = value
   key = value
   Structname:
       key = value
   Structname:
       key = value
...

哪里的Key和value直接从ElementNode读取或者从另一个文件读取placeholder的值在ElementTemplateNode里面

树有更好的结构吗?因为对于当前的,我必须先检查它是 StructNodeElementNode 还是 ElementTemplateNode

【问题讨论】:

  • 有趣的是你必须检查类型。听起来像一个多态性问题。也许更多地谈论它的那个方面。你在做什么操作需要检查Node的具体类型?
  • 首先,一旦您拥有继承并通过指向基类的指针保留对象,您就必须向基类添加虚拟析构函数,在您的情况下为Node
  • std::vector&lt;std::unique_ptr&lt;Node&gt;&gt; children; 小心这个。虽然这个构造是正确的,但如果你的结构深入增长,你可能会因为一长串独特的 ptr 破坏它们的孩子而导致析构函数溢出堆栈。而且您的基础结构缺少虚拟析构函数。
  • 顺便说一句,我不完全确定,但是像boost::property_tree 这样的东西不能满足你的需要吗?
  • @alagner 存储孩子的更好的方法是什么?

标签: c++ data-structures


【解决方案1】:

这是实现具有不同类型节点的树的典型结构。另一个变体是composite pattern

您描述的问题通常是由向节点询问他们知道什么引起的,而不是告诉他们该做什么。如果您反过来 (tell, don't ask),您可以摆脱这些检查并从多态性中受益。

不同类型的节点继承自Node。您可以使用统一接口设计您的树,并为Node 定义虚函数,然后可以针对不同类型的节点覆盖这些虚函数。然后调用该方法将做正确的事情,而不需要手动类型检查。为了生成输出字符串,您需要告诉根节点生成一个字符串。如果它是一个结构,它会添加标题并告诉它的孩子生成一个字符串,但如果它是一个叶子,它只会将键/值对添加到字符串中。无需从外部了解每个节点的任何信息。

如果探索树的操作不应该由树本身来实现,通常的做法是使用visitor pattern。最大的优势是您只需编写一次访问者,然后就可以轻松地将一种新的访问者专门用于不同的算法。同样,无需检查节点的类型。该模式确保为正确类型的节点调用正确的初等函数。

【讨论】:

  • 我也考虑过将打印添加到节点,但是我需要将另一个文档或指向它的指针传递给打印语句,以便我能够解析 @987654326 中的占位符@。这就是为什么我不确定目前的结构是否最合适
猜你喜欢
  • 1970-01-01
  • 2014-06-02
  • 2018-01-05
  • 1970-01-01
  • 2014-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多