私は数式を表すツリーを持っています。私は式ツリーの値を計算するために訪問者パターンを実装すると考えましたが、C++ではメソッドが同一であっても、型はそうではないので、訪問者を受け入れるメソッドがすべてのサブクラスになければならないので、自分自身を繰り返したくさんあります。訪問者パターンの代わりにenumsとswitchを使用する
class Node {
virtual void Acccept(Visitor *visitor) = 0;
};
class ConstantNode : Node {
virtual void Accept(Visitor *visitor) {
visitor->visit(this);
}
};
class VariableNode : Node {
virtual void Accept(Visitor *visitor) {
visitor->visit(this);
}
};
class Visitor {
virtual void visit(ConstantNode *node) = 0;
virtual void visit(VariableNode *node) = 0;
};
class CalculateVisitor : Visitor {
virtual void visit(ConstantNode *node) { /* code */ }
virtual void visit(VariableNode *node) { /* code */ }
};
これは、メソッドが仮想であるため、テンプレートノードを持つことができないという問題もあります。
各ノードごとに1つのケースがあり、ビジターパターンではなくメソッドで列挙型をオンにするだけで、列挙型の方がはるかに簡単です。
class Node {
enum NodeType {
Constant,
Variable
}
Node(NodeType type) : m_nodeType(type) {}
NodeType m_nodeType;
};
class ConstantNode {
ConstantNode() : Node(Constant) {}
};
class VariableNode {
VariableNode() : Node(Variable) {}
};
int calculate(Node* node) {
switch (node->m_nodeType) {
case Constant:
//...
case Variable:
//...
}
}
私は、列挙型のバージョンは動的なキャストが必要になります知っているが、全体的に同じコードの多くを繰り返す有することが好ましいようで、それがテンプレートノードなど(BinOpNode<std::plus>
)を可能にすることを意味します。
また、この繰り返しをすべて行う必要がないように、C++でビジターパターンを改善する方法がいくつかありますか?
(間違いのため申し訳ありませんが、stackoverflowのに直接コードを型付きが、それは実際のコードに基づいています)
EDIT:BinOpNode用:
template<class T>
class BinOpNode {
T m_op = T();
BinOpNode() : Node(BinOp) {}
};
//in calculate:
case BinOpNode:
BinOpNode* n = dynamic_cast<BinOpNode*>(node);
return n->m_op(calculate(n->m_left), calculate(n->m_right));
これはまったく簡単ではないようです。反復の量は同じです(ケースラベルと仮想関数)。また、テンプレートの処理方法についても説明していませんでした。 'case BinOp:'今何? –
すべての受諾機能が不要になるため、繰り返し回数が少なくなります。いずれの状況でもノードのコンストラクタが存在します。 –
新しい訪問者を追加するのに繰り返しは必要ありません。 switch/enumの場合とは逆の型を忘れることは避けてください。 – Jarod42