从带有参数的基本函数指针中调用基本方法

问题描述 投票:0回答:1

我正在使用“访客”图案遍历并打印正在操作的树的子代。为了进行缩进打印,我以如下样式指定缩进级别:

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

c++ function-pointers
1个回答
1
投票

据我了解,您应该有类似的东西:

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();
    // ...
};
© www.soinside.com 2019 - 2024. All rights reserved.