4

In C ++, I first encountered function pointers.
I tried to use this to make it similar to Action and Delegate in C #.
However, when declaring a function pointer, it is necessary to specify the type of the class in which the function exists.
ex) void (A :: * F) ();
Can I use a function pointer that can store a member function of any class?

In general, function pointers are used as shown in the code below.

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;
}

I want to use it like the code below.
is this possible?
Or is there something else to replace the function pointer?

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;
}

I solved the question through the answer.
Thanks!

#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;
}
  • Why can't you just make `AF` a static method or a global function? You don't have to access any member of class `A` anyway. – user202729 Jun 01 '19 at 08:32
  • I can't read answer with code in this moment but You can read this answer https://stackoverflow.com/questions/9568150/what-is-a-c-delegate And from me, read about auto type ane std::variant from C++ 17 – Drock Jun 01 '19 at 08:43
  • @Drock "read about auto type" - `auto` is not a type. It's just a keyword telling the compiler to deduce the correct type itself at initialization of the variable. The variable still has a static type and that type cannot change. For example; `int i = 42;` and `auto i = 42;` results in *exactly* the same. In both cases the stype of `i` is `int` and it will *stay* `int` forever. – Jesper Juhl Jun 01 '19 at 08:54
  • @Drock Just out of interest, why is it worth reading up on variant? – George Jun 01 '19 at 08:54
  • You can use the template `std::function` for member function pointers. The template type won't require the class. – Weak to Enuma Elish Jun 01 '19 at 09:03

2 Answers2

4

What you want to do is probably something like this. You can use std::function to hold a pointer to a member function bound to a specific instance.

#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;
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
snak
  • 6,483
  • 3
  • 23
  • 33
  • 3
    `std::bind` is sooo old-school. https://stackoverflow.com/q/1930903/5945883 I'd upvote lamda-based answer. – R2RT Jun 01 '19 at 09:23
  • Well, with lambda, now it no longer answers the question, I think, because both capturing a lambda with `function<>` and calling a method in the lambda are both trivial and nothing special. – snak Jun 01 '19 at 09:32
  • @snak Also more efficient that `bind` since the resulting object is smaller and in practice will not require memory allocation in `std::function`. –  Jun 01 '19 at 09:35
  • I have never used a lambda expression, so I made a little searching and understood. Thank you! – Lim Seungwook Jun 01 '19 at 09:47
  • @snak `B b2([&a] { a.AF(); });`, as already edited by Ted, answers question in 100% and saves OP headache when he decides to add any argument to delegated function. – R2RT Jun 01 '19 at 09:47
1

Here's a C# style implementation of the accepted answer, It is memory efficient and flexible as you can construct and delegate at different points of execution which a C# developer might expect to do:

#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;
}
Avin Kavish
  • 8,317
  • 1
  • 21
  • 36