如何用指向成员函数的指针切换?

How to switch with pointer to member functions?

好吧,我只想做一个带有函数指针和方法指针的“switch”。开关是,如果我调用方法 Run(),它将重定向到 A::RunOn()A::RunOff() 根据 Run ptr 指向这些成员函数。

我知道可以做到。我用普通 but I have searched and googled to do the same thing in 做到了,但运气不好。

class A
{
    typedef (void)(A::*RunPtr)(int);
    RunPtr RunMethod;

public:
    RunMethod Run;

    A()
    {
        Run = RunOff;
    }

    void SetOn(bool value)
    {
        if (value)
            Run = RunOn;
        else
            Run = RunOff;
    }

    void RunOn(int)
    {
        // RunOn stuff here
    }

    void RunOff(int)
    {
        // RunOff stuff here
    }
};

所以我可以调用 Run() 并且函数调用之间会有一个切换,我认为这比只做更有效率:

if (on)
    RunOn();
else
    RunOff();

不知道怎么做!

您的成员函数指针 typedef 是错误的(尽管显示的代码中存在其他问题)。你需要

typedef void(A::*RunPtr)(int);

或者你可以在using keyword的帮助下为classA的成员函数指针提供别名,如下所示:

using RunPtr = void(A::*)(int);
RunPtr RunMethod;

现在在SetOn中你可以如下进行成员指针赋值

void SetOn(bool value)
{
    RunMethod = value ? &A::RunOn : &A::RunOff;
}

现在,为了调用存储的成员函数指针,您可以/可以提供一个Run成员函数,如下所示:

void  Run(int arg)
{
    std::invoke(RunMethod, this, arg);
    // do something...
}

call to member function is a bit tricky。 但是,这可以使用更通用的 std::invoke from <functional> header (Since ).

来完成

完整示例如下:

#include <iostream>
#include <functional> //  std::invoke

class A
{
    using RunPtr = void(A::*)(int);
    // or with typedef
    // typedef void(A::*RunPtr)(int);
    RunPtr RunMethod;

public:
    void SetOn(bool value)
    {
        RunMethod = value ?  &A::RunOn : &A::RunOff;
    }

    void  Run(int arg)
    {
        std::invoke(RunMethod, this, arg);
        // do something...
    }

    void RunOn(int arg) { std::cout << "RunOn: " << arg << "\n"; }

    void RunOff(int arg) { std::cout << "RunOff: " << arg << "\n";  }
};

int main()
{
    A obj;
    obj.SetOn(true);
    obj.Run(1);       // prints: RunOn: 1  
    obj.SetOn(false);
    obj.Run(0);       // prints: RunOff: 0
}

(See a Demo)

一旦你修复了其中的语法错误,你的代码就可以正常工作,即:

  1. Class 需要 class.

  2. RunMethod Run;中,RunMethod不是类型,是成员变量。您 的意思是 改为使用 RunPtr Run;(并摆脱 RunMethod),但这对您来说效果不佳(请参阅下文了解原因)。

  3. Run = RunOn;Run = RunOff;中,需要对方法名进行全限定,并加上&运算符作为前缀,如Run = &A::RunOn; .

尝试以下操作:

class A {
public:
    typedef void (A::*RunPtr)(int);
    RunPtr Run;
     
    A()
    {
        Run = &A::RunOff;
    }
     
    void SetOn(bool value)
    {
        if (value)
            Run = &A::RunOn;
        else
            Run = &A::RunOff;
    }

    void RunOn(int param)
    {
        //RunOn stuff here
    }

    void RunOff(int param)
    {
        //RunOff stuff here
    }
};

但是请注意,即使您 可以 使用 Run 作为 public 方法指针,调用者仍然需要使用 operator.*operator->* 实际调用它,这看起来不太好,例如:

A a;
(a.*a.Run)(...);

Online Demo

如果你希望能够像 a.Run(...) 那样调用 Run() 那么你必须使 Run() 成为一个标准方法,并让它在内部使用一个方法指针,例如:

class A {
    typedef void (A::*RunPtr)(int);
    RunPtr RunMethod;

public:
    A()
    {
        RunMethod = &A::RunOff;
    }

    void SetOn(bool value)
    {
        if (value)
            RunMethod = &A::RunOn;
        else
            RunMethod = &A::RunOff;
    }

    void RunOn(int param)
    {
        //RunOn stuff here
        cout << "RunOn: " << param << endl;
    }

    void RunOff(int param)
    {
        //RunOff stuff here
        cout << "RunOff: " << param << endl;
    }
    
    void Run(int param)
    {
        (this->*RunMethod)(param);
    }
};
A a;
a.Run(...);

Online Demo