我正在使用“访客”图案遍历并打印正在操作的树的子代。为了进行缩进打印,我以如下样式指定缩进级别:
printCurrent();
indentLevel(); // increases static variable
Visitor::visit(elem); // which then prints the children's node data
unindentLevel(); // decreases static variable
为了使这个更好,我想实现一个函数,该函数将Visitor::visit
与参数elem
一起使用,并自动处理操作前(indentLevel()
)和操作后(unindentLevel()
)。 >
实现该功能之前,我需要定义一个函数指针,该指针将用作该函数的参数。但是,我无法指定指针的参数。例如,让我们看一下从PrintVisitor
派生的Visitor
:
void PrintVisitor::visit(BinaryExpr &elem) { std::cout << formatOutputStr({elem.getNodeName()}); this->incrementLevel(); Visitor::visit(elem); // <-- this is where I want to create a function pointer to this->decrementLevel(); }
想法基本上是
PrintVisitor
会完成与打印有关的所有事情,并且所有其他逻辑(例如,遍历逻辑)都将在基本类Visitor
中实现。因此,PrintVisitor::visit
需要执行其特定操作(例如,通过formatOutputStr打印),然后执行Visitor::visit
方法:
void PrintVisitor::visit(BinaryExpr &elem) { std::cout << formatOutputStr({elem.getNodeName()}); void (Visitor::*myPt)(BinaryExpr&) = &Visitor::visit; // declare function pointer executeIndented(myPt, elem); // pass function pointer myPt } // ... void executeIndented("Function f", "FunctionArgs elem") { // pre-action this->incrementLevel(); // main action: call function pointer (Visitor().*f)(elem); // call function pointer with arg //post-action this->decrementLevel(); }
我的目标是以某种方式实现在每个
PrintVisitor::visit
方法中始终同时调用操作前和操作后。为此,我认为将这些前后动作封装到另一个函数executeIndented
中可以确保这一点。
(Visitor().*myPt)(elem);
的语法在我看来有点奇怪,这真的是使用函数指针Visitor::visit
调用带有参数elem
的(基本)函数myPt
的正确方法吗?
//编辑
也可以使用(Visitor(*this).*myPt)(elem);
。这两种方式之间有什么区别,并且是首选的一种吗?// EDIT2希望现在对我要实现的目标的描述更加清晰。
我正在使用“访客”图案遍历并打印正在操作的树的子代。为了进行缩进打印,我以一种样式指定缩进级别:printCurrent(); indentLevel(); ...
据我了解,您应该有类似的东西:
struct TraversalVisitor : IVisitor
{
void visit(BinaryExpr &elem) final
{
pre_traversal_action(elem);
visit(elem.lhs);
action(elem);
visit(elem.rhs);
post_traversal_action(elem);
}
virtual void pre_traversal_action(BinaryExpr &elem) { /*Nothing */ }
virtual void action(BinaryExpr &elem) { /*Nothing */ }
virtual void post_traversal_action(BinaryExpr &elem) { /*Nothing */ }
void visit(UnaryExpr &elem) final;
// ...
};
struct PrintVisitor : TraversalVisitor
{
void pre_traversal_action(BinaryExpr &elem) override {
std::cout << formatOutputStr({elem.getNodeName()});
incrementLevel();
}
//void action(BinaryExpr &elem) override { /*Nothing */ }
void post_traversal_action(BinaryExpr &elem) override { decrementLevel(); }
// ...
private:
void formatOutputStr(const std::string&);
void incrementLevel();
void decrementLevel();
// ...
};