0

我正在尝试使用递归遍历树,但我遇到了一个问题,因为基类是模板类。下面是代码:

出现问题是因为当traverse调用 RootNode 函数时,它仍然对节点的所有子类使用 EmptyVisitor 类。但我不知道它是否有可能克服这个问题。我需要 TransformNode 来“知道”它使用的是 TransformVisitor 而不是 EmptyVisitor。我希望我能解释我的意思。

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> {
};

主文件

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知道从同一个基类派生的其他类。您的设计似乎有点过于模糊,并且与访问者模式无关。为什么不只使用普通的多态性?

这只是一个草图,因为使用多态性会使您的大部分模板工作过时,因此应该进一步重构。但是,这个简单的修复将引导您获得所需的结果:

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 回答