рекурсия через функцию производных классов шаблонного класса

0

Я пытаюсь пройти через дерево, используя рекурсию, но я столкнулся с проблемой, потому что базовый класс является классом шаблона. Вот приведенный ниже код:

Проблема возникает потому, что, когда RootNode traverse функция называется она по- прежнему использует класс 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> {
};

main.cpp

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

   return 0;
}

Вывод:

Empty Visitor
Empty Visitor

Ожидаемый результат:

Empty Visitor
Transform Visitor
Теги:
templates
recursion

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

Возможно, вы были заинтересованы в чем - то вроде этого или это?

  • 0
    имеет смысл. Спасибо!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню