使用参数从基函数指针调用基方法

Call base method from base function pointer with arguments

我正在使用访问者模式来遍历和打印我正在操作的树的子节点。为了缩进打印,我指定了如下样式的缩进级别:

printCurrent();
indentLevel();        // increases static variable
Visitor::visit(elem); // which then prints the children's node data
unindentLevel();      // decreases static variable

为了让它更好,我想实现一个函数,它接受带有参数 elemVisitor::visit 并自动处理预操作 (indentLevel()) 和 post-动作(unindentLevel()).

在实现该函数之前,我需要定义一个函数指针,用作该函数的参数。但是,我未能指定指针的参数。例如,让我们看一下从 Visitor:

派生的 PrintVisitor
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 完成与打印相关的所有事情,所有其他逻辑(例如,遍历逻辑)在基础 class 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 方法中始终调用预操作和 post 操作。为此,我认为将这些预操作和 post 操作封装到另一个函数 executeIndented 中是有意义的,它确保了

(Visitor().*myPt)(elem); 的语法对我来说有点奇怪,这真的是使用我的函数指针调用带有参数 elem 的(基本)函数 Visitor::visit 的正确方法吗myPt?

// 编辑 使用 (Visitor(*this).*myPt)(elem); 也可以。这两种方式有什么区别,哪一种更受青睐?

// 编辑2 希望现在对我要实现的目标的描述更加清楚。

据我了解,你应该有这样的东西:

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();
    // ...
};

而您尝试实现类似的东西:

struct Visitor : IVisitor
{
    virtual visit(BinaryExpr &elem)
    {
        visit(elem.lhs);
        visit(elem.rhs);
    }
// ...
};

struct PrintVisitor : Visitor
{
private:
    void formatOutputStr(const std::string&);
    void incrementLevel();
    void decrementLevel();

    void executeIndented(Expr& elem) {
        incrementLevel(); // pre-action

        // Traversal
        Visitor::visit(elem);

        decrementLevel(); // post-action
    }

    void visit(BinaryExpr &elem) override {
        std::cout << formatOutputStr({elem.getNodeName()});

        executeIndented(elem);
    }

    // ...
};

你的尝试,IMO,只是因式分解 PrintVisitor,没有强制执行一些遍历策略。