正直なところ、私がそれを見れば見るほど、それは私にとって典型的なビジターアプリケーションのように見えます。
クラスにインテリジェンスを実装することは避け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
階層はそれほどオープンではありません。これは、非巡回ビジターを使用して軽減できます。しかし、私はめったにそれを必要としませんでした。
能力を「拡張」するために、実行する「アクション」(消去、複製など)を持っVisitor::visit
て返し、実際に持っている2つのループでこれを処理することができます。いくつかのトリックを使用して、1つのループに減らすことができます...MemberBase::accept