老实说,我看的越多,它对我来说就像一个典型的访客应用程序。
我建议避免在您的Container
班级中实施任何智能,而是将操作委托给特定Visitor
班级。Visitor
可以为基础提供某种方式来安全地与底层容器结构交互(擦除/插入)。
// MemberBase.hpp
class Visitor;
class MemberBase {
public:
virtual MemberBase* clone() const = 0;
virtual void accept(Visitor&) = 0;
virtual void accept(Visitor&) const = 0;
}; // class MemberBase
// Visitor.hpp
class Member1;
class Member2;
class Visitor {
public:
virtual void visit(Member1&) = 0;
virtual void visit(Member1 const&) = 0;
virtual void visit(Member2&) = 0;
virtual void visit(Member2 const&) = 0;
};
// Container.hpp
#include <MemberBase.hpp>
class Container {
public:
void accept(Visitor& v) {
BOOST_FOREACH(MemberBase& mb, _members) {
mb.accept(v);
}
}
void accept(Visitor& v) const {
BOOST_FOREACH(MemberBase const& mb, _members) {
mb.accept(v);
}
}
private:
boost::ptr_vector<MemberBase> _members;
};
然后你需要实现成员的accept
方法。它是纯机械的。
// Member1.hpp
#include <MemberBase.hpp>
class Member1: public MemberBase {
public:
virtual Member1* clone() const { return new Member1(*this); }
virtual void accept(Visitor& v);
virtual void accept(Visitor& v) const;
};
// Member1.cpp
#include <Member1.hpp>
#include <Visitor.hpp>
void Member1::accept(Visitor& v) { v.visit(*this); }
void Member1::accept(Visitor& v) const { v.visit(*this); }
最后你可以实现一个访问者:
// CountVisitor.hpp
#include <Visitor.hpp>
class CountVisitor: public Visitor {
public:
CountVisitor(): _count(0) {}
size_t count() const { return _count; }
virtual void visit(Member1&);
virtual void visit(Member1 const&);
virtual void visit(Member2&);
virtual void visit(Member2 const&);
private:
size_t _count;
};
// CountVisitor.cpp
#include <CountVisitor.hpp>
//#include <Member1.hpp> // where you would include, but unnecessary here
void CountVisitor::visit(Member1&) { ++_count; }
void CountVisitor::visit(Member1 const&) { ++_count; }
void CountVisitor::visit(Member2&) { ++_count; }
void CountVisitor::visit(Member2 const&) { ++_count; }
您将其用作:
// main.cpp
#include <iostream>
#include <Container.hpp>
#include <CountVisitor.hpp>
int main() {
Container const c = /* something */;
CountVisitor cv;
c.accept(cv);
std::cout << cv.count() << " items in the container\n";
}
这种设计的缺点是visit
需要为每个直接派生自 的新类实现一个新方法MemberBase
,因此MemberBase
层次结构不是那么开放。这可以使用Acyclic Visitor来缓解;但是,我很少需要它。
要“扩展”能力,您可以拥有Visitor::visit
并MemberBase::accept
返回要执行的“动作”(擦除、克隆等),并在您实际拥有的两个循环中处理此问题。可以使用一些技巧将其简化为一个循环...