0

再帰を使用してツリーをトラバースしようとしていますが、基本クラスがテンプレート クラスであるため、問題が発生しています。以下にコードを示します。

問題が発生するのは、RootNodetraverse関数が呼び出されたときに、ノードのすべての子クラスに EmptyVisitor クラスが引き続き使用されるためです。しかし、この問題を克服できるかどうかはわかりません。EmptyVisitor ではなく TransformVisitor を使用していることを「知る」には、TransformNode が必要です。私の言いたいことを説明できれば幸いです。

class BaseNode {
public:
    typedef std::set<BaseNode *> ChildSet;

protected:
    ChildSet mChildren;
    BaseNode * mParent;

public:
    BaseNode(BaseNode * parent=0) : mParent(parent) {}
    ~BaseNode() {}

    BaseNode * addChild(BaseNode * node); //adds `node` to `mChildren`
    inline BaseNode * getParent() { return mParent; }

    inline const ChildSet &getChildren() const { return mChildren; }
    inline ChildSet &getChildren() { return mChildren; }
};

class EmptyVisitor {
public:
    static void visit(BaseNode * node) {std::cout << "Empty Visitor\n";}
};

class TransformVisitor {
    static void visit(BaseNode * node) {
       std::cout << "Transform Visitor\n";
    }
};

template<class Visitor>
class Node : public BaseNode {
public:

    void traverse() {
        traverse(this);
    }

    void traverse(Node * node) {
        Visitor::visit(this);

        for(ChildSet::iterator i = node->getChildren().begin(); i != node->getChildren().end(); ++i) {
            traverse(static_cast<Node*>((*i)));
        }
    }

};

class RootNode : public Node<EmptyVisitor> {
};

class TransformNode : public Node<TransformVisitor> {
};

main.cpp

int main() {
    RootNode * root = new RootNode;
    root->addChild(new TransformNode);
    root->traverse();

   return 0;
}

出力:

Empty Visitor
Empty Visitor

期待される出力:

Empty Visitor
Transform Visitor
4

1 に答える 1

1

RootNode同じ基本クラスから派生した他のクラスをクラスが知る方法はありません。あなたのデザインは難読化されすぎているように見えますが、実際にはVisitorパターンとは何の関係もありません。通常のポリモーフィズムを使用しないのはなぜですか?

ポリモーフィズムを使用するとほとんどのテンプレートの作業が時代遅れになるため、これは単なるスケッチです。そのため、さらにリファクタリングする必要があります。ただし、この簡単な修正により、目的の結果が得られます。

template<class Visitor>
class Node : public BaseNode {
public:

    void traverse() {
        traverse(this);
    }

    void traverse(Node * node) {
        visit();

        for(ChildSet::iterator i = node->getChildren().begin();
            i != node->getChildren().end();
            ++i) {
            traverse(static_cast<Node*>((*i)));
        }
    }

    virtual void visit()
    {
        Visitor::visit(this);
    }
};

class TransformNode : public Node<TransformVisitor> {
    void visit()
    {
        TransformVisitor::visit(this);
    }
};

おそらく、あなたはこのようなものに興味がありましか?

于 2013-10-07T10:59:14.313 に答える