C++ 迭代节点层次结构-访问者和复合?

C++ 迭代节点层次结构-访问者和复合?,c++,oop,design-patterns,composite,visitor,C++,Oop,Design Patterns,Composite,Visitor,让我们设想一下,我有一个节点集合,稍后用于渲染器类。然后我有一个访问者类,可以访问节点或整个集合。这很简单,因为在我的节点集合中,它只是std::list的包装器,没有多少额外的方法 问题是我希望节点有一个树状结构(而不是简单的列表),这样一个节点可以有一个父节点和n个子节点。这将是方便的,因为我希望能够传递给我的渲染器一个节点,并渲染“低于”该节点的所有内容。答案可能是复合的 如何将访问者和复合应用程序结合使用?我已经读到这通常是一个很好的组合,但我的实现看起来很糟糕。。。我遗漏了一些东西。我

让我们设想一下,我有一个节点集合,稍后用于渲染器类。然后我有一个访问者类,可以访问节点或整个集合。这很简单,因为在我的节点集合中,它只是std::list的包装器,没有多少额外的方法

问题是我希望节点有一个树状结构(而不是简单的列表),这样一个节点可以有一个父节点和n个子节点。这将是方便的,因为我希望能够传递给我的渲染器一个节点,并渲染“低于”该节点的所有内容。答案可能是复合的


如何将访问者和复合应用程序结合使用?我已经读到这通常是一个很好的组合,但我的实现看起来很糟糕。。。我遗漏了一些东西。

我为我们的系统实现了一些非常类似的东西。我想要一种方法来组成几何对象的层次结构,并将它们渲染到体积中。我使用复合模式来组合我的描述(根是节点,然后派生的子节点是复合节点(节点列表)

CompositeNode有一个方法accept(),它接受一个访问者(visitor),然后在accept()中执行visitor->visit(this)

因此,访问者层次结构的基类为NodeVisitor,派生访问者为RenderVisitor(呈现对象)、ReportVisitor(将节点信息转储到文本中)。您的基类需要同时接受基类和专用节点类型

所以,是的,combo是有效的,我有可用的代码,但我同意设计比在线阅读(Wiki或玩具示例)更费劲


希望这有帮助这里有一个简单的例子:

struct NodeVisitor;

struct Node
{
  virtual ~Node() {}
  virtual void accept(NodeVisitor &v);
};

struct CompositeNode : public Node
{
  virtual void accept(NodeVisitor &v);
  std::list<NodePtr> nodes_;
};

struct NodeVisitor
{
  virtual ~NodeVisitor() {}
  virtual void visit(Node &n) = 0;
  virtual void visit(CompositeNode &cn)
  {
    for(std::list<NodePtr>::iterator it = cn.nodes_.begin(), end = cn.nodes_.end(); it != end; ++it)
    {
      (*it)->accept(*this);
    }
  }
};
struct节点设备;
结构体类型
{
虚拟~Node(){}
虚拟无效接受(NodeVisitor&v);
};
结构复合节点:公共节点
{
虚拟无效接受(NodeVisitor&v);
std::列出节点;
};
结构节点设备
{
虚拟~NodeVisitor(){}
虚拟无效访问(节点&n)=0;
虚拟虚拟虚拟访问(CompositeNode&cn)
{
对于(std::list::iterator it=cn.nodes\uu.begin(),end=cn.nodes\uu.end();it!=end;+it)
{
(*it)->接受(*此);
}
}
};

< /代码> 如果您希望访问者也知道树的结构(例如,它正在访问的深度或来自树根的路径),可以考虑使用分层访问者模式。 这在下面的部分中描述得有点冗长


它还显示了如何跳过“无趣”分支。

为什么要在
NodeVisitor
中调用节点子节点的
accept
s?@user35443:因为否则访问将停止,并且由于OP询问如何将访问者与需要包括对组合中所有节点的访问的组合相结合,否则它将被拒绝t be Visitor.Info about Visitor:。Info about composite:是的,但我的意思是,我已经研究了Hierarchy一段时间了,无论我在哪里,我都在节点中发现了复合成员的迭代,而不是Visitor。@user35443:好吧,你可以用任何一种方法来做。每种方法都有优点和缺点。在Visitor中进行迭代会给你更多的灵活性在复合节点中这样做,让我们编写一次,然后忘记它。通常对于我遇到的大多数实际情况,我需要额外的灵活性。