обратный вызов в C ++ struct - PullRequest
       31

обратный вызов в C ++ struct

0 голосов
/ 08 октября 2018

Я пытался реализовать функцию обратного вызова в C ++.Внутри класса у меня есть структура, несколько методов и метод, который создает экземпляр структуры с одним из других методов в качестве аргумента.

Структура имеет много других переменных, но здесь изображена иллюстрация:

class MYCLASS
{
public:
    MYCLASS();

    struct TEST{
        std::function<int(int)> foo;
    };

    int plus(int x){
        return x + 1;
    }

    int minus(int x){
        return x - 1;
    }

    void sim(){
        TEST T;             // make an instance of TEST
        T.foo = plus(5);    // assign TEST.foo a function (plus or minus)  
        T.foo();            // call the method we assigned
    }
};

В методе sim я хочу создать экземпляр test и дать ему либоplus или minus, в зависимости от некоторого критерия.Обе строки, где я пытаюсь дать экземплярную функцию T a plus, и впоследствии вызываем ее, неверны.

Ответы [ 2 ]

0 голосов
/ 09 октября 2018

Опция - 1

Если функции-члены plus() и minus() достаточно просты, как вы показали, вы можете сделать их лямбда-функциями внутри структуры TEST.Поскольку лямбда без захвата может храниться в типизированных указателях функций , следующее будет делать то, что вы хотите. См. Демонстрационную версию в реальном времени

#include <iostream>
class MYCLASS
{
    int m_var = 5; // just for demonstration
public:
    MYCLASS() = default;
    struct TEST
    {
        using fPtrType = int(*)(int);   // function pointer type
        const fPtrType foo1 = [](int x) { return x + 1; };  // plus function
        const fPtrType foo2 = [](int x) { return x - 1; };  // minus function
    };

    void sim()
    {
        TEST T;
        std::cout << "Answer from int PLUS(int): " << T.foo1(m_var) << std::endl;
        std::cout << "Answer from int MINUS(int): " << T.foo2(m_var) << std::endl;
    }
};

Опция - 2

Если вышеперечисленное сильно меняет ваш код, снова используйте указатель типизированной функции для функций-членов и выполнитеследующее;что позволит избежать ненужного копирования (путем захвата) экземпляра класса в лямбду и создание шаблона и других проблем с производительностью приходит с std::function.

См. демо-версию

#include <iostream>    
class MYCLASS
{
    using fPtrType = int(MYCLASS::*)(int); // class member function pointer type
public:
    MYCLASS() = default;
    struct TEST { fPtrType foo = nullptr; };

    int plus(int x) { return x + 1; }
    int minus(int x) { return x - 1; }

    void sim()
    {
        TEST T;
        T.foo = &MYCLASS::plus; // now you can
        std::cout << "Answer from int PLUS(int): " << (this->*T.MYCLASS::TEST::foo)(5) << std::endl;
                                                     //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ syntax would be a bit ugly
        // later same ptr variable for minus()
        T.foo = &MYCLASS::minus;
        int answer = (this->*T.MYCLASS::TEST::foo)(5);
        std::cout << "Answer from int MINUS(int): " << answer << std::endl;
    }
};

int main()
{
    MYCLASS obj;
    obj.sim();
    return 0;
}

Выход:

Answer from int PLUS(int): 6
Answer from int MINUS(int): 4
0 голосов
/ 08 октября 2018

Если вы хотите отложить вызов до T.foo, то вы можете использовать лямбда-выражения следующим образом:

    T.foo = [this](int x) { return plus(x); };
    T.foo(5);
...