lambdas作为实例函数指针

时间:2014-08-15 13:33:42

标签: c++ lambda function-pointers

我的类型aButton有一个函数指针,所以我可以为每个按钮定义自定义动作,虽然最简单的方法是创建一个lambda并取消引用它并将其传递给该aButton实例的函数指针,我需要非对静态访问按钮类范围之外的对象

但是我一直在试图弄清楚如何将其转换为正确的类型以及如何调用它而不会出现以下错误...我没有看到很多人对此有好运,并且使用功能不会'看起来我可以传递上下文???

    // Example program
    #include <iostream>
    #include <string>

    int global1 = 0;
    int global2 = 5;

    class aButton {
    public:
        int status, oldStatus;
        aButton(int initStatus) { oldStatus = status = initStatus; }
        int (aButton::*action)();
    };

    class Thingy {
    private:
        int mode  = 1;
        int value = 0;
    public:
        void reset() { value = 0; }
        void setMode(int newMode) { mode = newMode; }
        void increment() { value = value + global2; }
        //accessors & mutators
    };

    void specialFunction(Thingy *thingyToWorkOn) {
        //do stuff...
    }
    void anotherSpecialFunction(Thingy *firstThingy, Thingy *secondThingy) {
        //more stuff...
    }

    int main() {

        Thingy one;
        Thingy two;

        aButton *on = new aButton(0);
        aButton *speedUp = new aButton(0);

        on->action = &(     //error: taking address of temporary [-fpermissive]
            [&]() {         //error: cannot convert 'main()::<lambda()>*' to 'int (aButton::*)()' in assignment

                //some specific stuff....
                global1 = 1;
                if (global2 < 10) {
                    global2++;
                }
                one.reset();
                two.reset();
                anotherSpecialFunction(&one, &two);
                std::cout << "on action \n";
                return 1;
            }
        );

        speedUp->action = &(    //error: taking address of temporary [-fpermissive]
            [&]() {             //error: cannot convert 'main()::<lambda()>*' to 'int (aButton::*)()' in assignment

                //some specific stuff....
                if (global1) {
                    one.setMode(global2);
                    two.setMode(global2);
                    specialFunction(&one);
                    specialFunction(&two);
                    std::cout << "speedUp action \n";
                    return 1;
                }
                return 0;
            }
        );


        for(int i=0; i<5; i++) {
            //if on pushed
            (on->(on->action))();           //error: expected unqualified-id before '(

            //if speedUp pushed
            (speedUp->(speedUp->action))(); //error: expected unqualified-id before '(
        }

    }

3 个答案:

答案 0 :(得分:2)

我认为您希望aButton::action属于std::function<int()>类型(读取:不执行任何操作的函数并返回int)而不是int (aButton::*)。这需要<functional>标头。通过该更改,您的分配可以保持不变(减去运算符的前导地址),但是如您所知,您需要使用-> int显式声明返回类型。这些电话只是采取形式(例如):

on->action();

另一个注意事项:通过引用非常小心地捕获局部变量(onetwo)。如果函数确实是main,那么我认为没关系,因为main在程序结束之前不会返回,否则就会有问题。

答案 1 :(得分:0)

您不能将指向lambda的指针指定给指向成员函数的指针。指向成员函数的指针可能仅指向成员函数。

您确实可以使用std::function中的<functional>。将您的action声明为

std::function<int()> action;

因此,您将使用全局函数而不是使用成员函数。当然你需要摆脱lambdas的&运算符。您需要修改调用action的方式。

答案 2 :(得分:0)

谢谢大家,我猜功能性毕竟是我想要的...这似乎做了我想要的http://cpp.sh/8ll我想我只是困惑因为很多函数示例将它们作为回调的参数而不是

    // Example program
    #include <iostream>
    #include <string>
    #include <functional>

    int global1 = 0;
    int global2 = 5;

    class aButton {
    public:
        int status, oldStatus;
        aButton(int initStatus) { oldStatus = status = initStatus; }
        std::function<int()> action;
    };

    class Thingy {
    private:
        int mode  = 1;
        int value = 0;
    public:
        void reset() { value = 0; }
        void setMode(int newMode) { mode = newMode; }
        void increment() { value = value + global2; }
        //...
    };

    void specialFunction(Thingy *thingyToWorkOn) {
        //do stuff...
    }
    void anotherSpecialFunction(Thingy *firstThingy, Thingy *secondThingy) {
        //more stuff...
    }

    int main() {

        Thingy one;
        Thingy two;

        aButton *on = new aButton(0);
        aButton *speedUp = new aButton(0);

        on->action = std::function<int()>(
            [&]() -> int{

                //some specific stuff....
                global1 = 1;
                if (global2 < 10) {
                    global2++;
                }
                one.reset();
                two.reset();
                anotherSpecialFunction(&one, &two);
                std::cout << "on action \n";
                return 1;
            }
        );

        speedUp->action = std::function<int()>(
            [&]() -> int{

                //some specific stuff....
                if (global1) {
                    one.setMode(global2);
                    two.setMode(global2);
                    specialFunction(&one);
                    specialFunction(&two);
                    std::cout << "speedUp action \n";
                    return 1;
                }
                return 0;
            }
        );


        for(int i=0; i<5; i++) {
            //if on pushed
            on->action();

            //if speedUp pushed
            speedUp->action();
        }

    }