Я пытаюсь пройти через дерево, используя рекурсию, но я столкнулся с проблемой, потому что базовый класс является классом шаблона. Вот приведенный ниже код:
Проблема возникает потому, что, когда 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
Для класса 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);
}
};
Возможно, вы были заинтересованы в чем - то вроде этого или это?