在类声明中处理指向成员函数的指针

Juggling with pointer-to-member-functions within class declaration

本文关键字:成员 函数 指针 声明 处理      更新时间:2023-10-16

我正在尝试让成员函数即时重定向到其他成员函数。以下是我想要实现的一些归结的伪代码:

class Foo
{
    public:
            Foo();
            int counter = 0;
            void slaveA() { counter++; };
            void slaveB() { counter--; };
            void (*master)() = &slaveA;
            void toggleSlave()
            {
                _useB = !_useB;
                if (_useB)
                    master = &slaveB;
                else
                    master = &slaveA;
            }
    private:
            boolean _useB = false;
}; 

Foo foo;
void setup()
{
    Serial.begin(9600);
}
void loop()
{
    if (random(2) == 0)
        foo.toggleSlave();
    foo.master();
    Serial.println(foo.counter);
    delay(500);
}

但是,无论我做什么,我都会遇到这些错误:

cannot convert 'void (Foo::*)()' to 'void (*)()' in initialization
cannot convert 'void (Foo::*)()' to 'void (*)()' in assignment

在我的主项目中,相当于 master 的调用速度将与硬件允许的至少 5 个从属站一样快,这就是为什么我试图在函数指针之间切换而不是在 master 中放置 if-else 的原因。

我读过一堆东西,说静态函数将是首选方法,但我需要 slave 方法能够操作成员变量,理想情况下,我希望所有内容都包含在类声明中,因此从技术上讲,对象引用随时可供所有涉及的成员函数使用。

这样的事情可能吗?

由于从属是非静态成员函数,因此master需要是指向成员函数的指针,而不是指向函数的指针。代码如下所示:

class Foo
{
    public:
            Foo();
            int counter = 0;
            void slaveA() { counter++; };
            void slaveB() { counter--; };
            void (Foo::*master)() = &Foo::slaveA;
            void toggleSlave()
            {
                _useB = !_useB;
                if (_useB)
                    master = &Foo::slaveB;
                else
                    master = &Foo::slaveA;
            }
    private:
            bool _useB = false;
};
void loop()
{
    if (random(2) == 0)
        foo.toggleSlave();
    (foo.*foo.master)();
    Serial.println(foo.counter);
    delay(500);
}

[现场示例]

由于语法(foo.*foo.master)()相当丑陋,我建议master foo和成员指针中的函数及其实现细节:

class Foo
{
    public:
            Foo();
            int counter = 0;
            void slaveA() { counter++; };
            void slaveB() { counter--; };
            void master() {
              (this->*_master)();
            }
            void toggleSlave()
            {
                _useB = !_useB;
                if (_useB)
                    _master = &Foo::slaveB;
                else
                    _master = &Foo::slaveA;
            }
    private:
            void (Foo::*_master)() = &Foo::slaveA;
            bool _useB = false;
};
void loop()
{
    if (random(2) == 0)
        foo.toggleSlave();
    foo.master();
    Serial.println(foo.counter);
    delay(500);
}