gpt4 book ai didi

c++ - 如何将访问者界面适配为迭代器界面?

转载 作者:可可西里 更新时间:2023-11-01 16:36:35 24 4
gpt4 key购买 nike

我想知道是否有一个好的设计模式或成语来实现以下内容:

You have an existing class that provides only a visitor interface, as follows

class Visitor {
public:
virtual ~Visitor() { }
virtual void visit(Node *n) = 0;
};

class Tree {
public:
void accept(Visitor *v);
};

And you want to have an interface that can be used as follows, which should iterate through the tree in the same order that the visitor would have its visit function called.

for(iterator it(...), ite(...); it != ite; ++it) {
/* process node */
}

问题似乎是当我们只是调用visit时,我们失去了控制,不能暂时“回到”循环体去执行一个节点的 Action 。这看起来应该经常出现在现实世界的程序中。知道如何解决吗?

最佳答案

在一般情况下,我不认为这是可能的,至少不干净。

至少按照通常的定义,迭代器期望处理同类集合。即,迭代器通常定义如下:

template <class Element>
class iterator // ...

...所以特定的迭代器只能处理一种特定类型的元素。要处理不同的类型,您最多可以创建一个指向基类(指针/引用)的迭代器,并让它处理派生类的对象。

相比之下,编写这样的访问者非常容易:

class MyVisitor {
public:
void VisitOneType(OneType const *element);
void VisitAnotherType(AnotherType const *element);
};

这可以访问 OneTypeAnotherType 的节点,即使这两者完全无关。基本上,您的 Visitor 类中有一个 Visit 成员函数,用于它能够访问的每种不同类型的

从稍微不同的角度来看,迭代器基本上是一种特殊形式的访问者,它只适用于一种类型的对象。您交换了对访问模式的更多控制,以换取失去访问不相关类型对象的能力。

如果你只需要处理一个类型(尽管那个类型可能是一个基类,而被访问的对象是各种派生类型),那么显而易见的方法是建立一个访问对象的“桥梁”类(Tree 节点,在您的示例中),当它的 visit 被调用时,它只是将它正在访问的节点的地址复制到一些支持迭代器的集合中:

template <class T>
class Bridge {
std::vector<T *> nodes;
public:
virtual void visit(T *n) {
nodes.push_back(n);
}

typedef std::vector<T *>::iterator iterator;

iterator begin() { return nodes.begin(); }
iterator end() { return nodes.end(); }
};

使用这将是一个两步过程:首先像访问者通常那样访问节点,然后将感兴趣的节点收集在一起,您可以像访问任何其他提供迭代器的集合一样迭代它们。那时,您的访问模式仅受您在桥中使用的集合提供的迭代器类的限制。

关于c++ - 如何将访问者界面适配为迭代器界面?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5507875/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com