c++ указатель на функцию-член, замена __close

Некоторое время назад Borland представила в своей среде BCB расширение для языка C++. Это расширение является ключевым словом __close. Вопрос в том, можно ли реализовать такую ​​функциональность на простом C++ или C++11? Если вы не знакомы с ключевым словом __close, в приведенном ниже коде приведены пояснения в комментариях.

Заранее спасибо! Торено

#include <stdio.h>

// __closure keyword is used here !
typedef void (__closure * MemberCallback)(int x, int y, int z);

class A
{
    private:

        MemberCallback callback;


    public:

        A() : callback(NULL)
        {
        }

        void setCallback(MemberCallback newCallback)
        {
            callback = newCallback;
        }

        void call(int x, int y, int z)
        {
            if(callback)
                callback(x, y, z);
            else
                printf("NOT SET(%i, %i, %i)\n", x, y, z);
        }
};

class B
{
    public:

        void func1(int x, int y, int z)
        {
            printf("FUNC 1(%i, %i, %i)\n", x, y, z);
        }

        void func2(int x, int y, int z)
        {
            printf("FUNC 2(%i, %i, %i)\n", x, y, z);
        }

};

int main()
{
    // A and B classes do not know about each other. There is no possibility
    // to for inheritance because B class can implement multiple instances
    // of callback function
    A a;
    B b;

    a.call(1, 2, 3);  // Prints: NOT SET(1, 2, 3)

    a.setCallback(b.func1);
    a.call(4, 5, 6);  // Prints: FUNC 1(4, 5, 6)

    a.setCallback(b.func2);
    a.call(7, 8, 9);  // Prints: FUNC 2(7, 8, 9)

    return 0;
}

person Community    schedule 26.07.2015    source источник


Ответы (2)


std::function — это именно то, что вам нужно. Если вы хотите узнать, как такой механизм реализован в библиотеке, вот хорошая серия статей на эту тему. Объедините это с лямбда-функциями для захвата локальных переменных.

person UnknownGosu    schedule 26.07.2015
comment
Большой! Это то, что я искал :) Спасибо! - person ; 26.07.2015
comment
на самом деле я преобразовал typedef std::function<void(int x, int y, int z)> MemberCallback; и вызов функции в: a.setCallback( [&b](int x, int y, int z) { b.func1(x, y, z); } );, но получил ошибку: термин не оценивается как функция, принимающая 3 аргумента. Есть ли у вас какие-либо предложения? - person ; 26.07.2015
comment
Работает отлично! Спасибо! :) - person ; 26.07.2015

Перефразируйте предыдущий ответ с полным кодом для таких, как я, которым нужна краткая ссылка на общий шаблон:

#include <functional>
#include <stdio.h>

// __closure replacement
typedef std::function<void(int x, int y, int z)>    MemberCallback;

class A
{
public:
    void setCallback( MemberCallback newCallback ) {
        callback_ = newCallback;
    }
    void call( int x, int y, int z ) {
        if ( callback_ )
            callback_( x, y, z );
        else
            printf( "NOT SET(%i, %i, %i)\n", x, y, z );
    }

private:
    MemberCallback  callback_;
};

class B
{
public:
    void func1( int x, int y, int z ) {
        printf( "FUNC 1(%i, %i, %i)\n", x, y, z );
    }
    void func2( int x, int y, int z ) {
        printf( "FUNC 2(%i, %i, %i)\n", x, y, z );
    }
};

int main( )
{
    // A and B classes do not know about each other. There is no possibility
    // to for inheritance because B class can implement multiple instances
    // of callback function
    A a;
    B b;

    a.call( 1, 2, 3 );  // Prints: NOT SET(1, 2, 3)

    a.setCallback( [&b](int x, int y, int z){ b.func1(x, y, z); } );
    a.call( 4, 5, 6 );      // Prints: FUNC 1(4, 5, 6)

    a.setCallback( [&b](int x, int y, int z){ b.func2(x, y, z); } );
    a.call( 7, 8, 9 );      // Prints: FUNC 2(7, 8, 9)

    return 0;
}

Вывод:

NOT SET(1, 2, 3)
FUNC 1(4, 5, 6)
FUNC 2(7, 8, 9)
person nlucas    schedule 25.11.2019