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

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

我知道这是可以做到的。我是用普通的c 语言完成的,但我已经搜索并用 google 搜索了在c++ 中做同样的事情,但没有运气。

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

或者你可以通过关键字A的帮助为类的成员函数指针提供别名,如下所示:using

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...
}

对成员函数的调用有点棘手。但是,这可以使用更通用的std::invokefrom <functional>header (Since c++17 ) 来完成。

这是完整的示例:

#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
}

(见演示)


回答

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

  1. Class需要是class

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

  3. Run = RunOn;and 中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像这样使用公共方法指针,调用者仍然需要使用operator.*operator->*实际调用它,这看起来不太好,例如:

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

在线演示

如果你想能够Run()像那样调用,a.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(...);

在线演示


以上是如何使用指向成员函数的指针进行切换?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>