Могу ли я использовать указатели функций C ++, например, C #'s Action? - PullRequest
4 голосов
/ 01 июня 2019

В C ++ я впервые столкнулся с указателями на функции.
Я попытался использовать это, чтобы сделать его похожим на Action и Delegate в C #.
Однако при объявлении указателя на функцию необходимо указатьтип класса, в котором существует функция.
ex) void (A :: * F) ();
Можно ли использовать указатель на функцию, которая может хранить функцию-член любого класса?

Обычно используются указатели функций, как показано в приведенном ниже коде.

class A {
public:
    void AF() { cout << "A::F" << endl; }
};

class B {
public:
    void(A::*BF)();
};

int main()
{
    A a;
    B b;

    b.BF = &A::AF;
    (a.*b.BF)();

    return 0;
}

Я хочу использовать его, как показано ниже.
возможно ли это?
ИлиЕсть ли что-то еще, чтобы заменить указатель функции?

class A {
public:
    void AF() { cout << "A::F" << endl; }
};

class B {
public:
    void(* BF)();
};

int main()
{
    A a;
    B b;

    b.BF = a.AF;

    return 0;
}

Я решил вопрос через ответ.
Спасибо!

#include <functional>
#include <iostream>

class A {
public:
    void AF() { std::cout << "A::F" << std::endl; }
};

class C {
public:
    void CF() { std::cout << "C::F" << std::endl; }
};

class B {
public:
    B(){}
    std::function<void()> BF;
};

int main() {
    A a;
    C c;
    B b;
    b.BF = std::bind(&A::AF, &a);
    b.BF();
    b.BF = std::bind(&C::CF, &c);
    b.BF();

    int i;
    std::cin >> i;
    return 0;
}

Ответы [ 2 ]

4 голосов
/ 01 июня 2019

То, что вы хотите сделать, это что-то вроде этого. Вы можете использовать std::function для хранения указателя на функцию-член, связанную с конкретным экземпляром.

#include <functional>
#include <iostream>

class A {
public:
    void AF() { std::cout << "A::F" << std::endl; }
};

class B {
public:
    B(const std::function<void()>& bf) : BF(bf) {}
    std::function<void()> BF;
};

int main() {
    A a;
    B b1(std::bind(&A::AF, &a)); // using std::bind
    B b2([&a] { a.AF(); });      // using a lambda

    b1.BF();
    b2.BF();

    return 0;
}
1 голос
/ 01 июня 2019

Вот реализация принятого ответа в стиле C #. Она эффективна в памяти и гибка, так как вы можете создавать и делегировать в разных точках выполнения, которые может ожидать разработчик C #:

#include <iostream>
#include <functional>

using namespace std;

class A {
public:
    void AF() { cout << "A::F" << endl; }
    void BF() { cout << "B::F" << endl; }
};

class B {
public:
    std::function<void()> Delegate;
};

int main() {
    A a;
    B b;

    b.Delegate = std::bind(&A::AF, &a);
    b.Delegate();

    b.Delegate = [&a] { a.BF(); };
    b.Delegate();
    return 0;
}
...