1

I have two classes, say A and B; I want to store a function pointer of B in a wrapper function<void()> in A.

The ultimate goal is to be able to call OnRender() at multiple places in A, but OnRender() is defined at runtime (say I want to choose one B among many).

How could this be done ?

class A
{
public:
    function<void()> OnRender{}; // I want to use this
    void (B::*OnRender)(){}; // I want to avoid this
}

class B
{
public:
    auto SomeJob() -> void;
}

I could store a function pointer like this:

someA.OnRender = &B::SomeJob;
// OK if I use void (B::*OnRender)(){};

But I also want to avoid referencing the class B in A.

ANSWER:

I can store a lambda like this:

someIntanceOfA.OnRender = [&](){ someB->SomeJob(); };
// OK if I use function<void()> OnRender{};

Or with safety measures:

someA.OnRender = [&](){ if(somB != nullptr) someB->SomeJob(); };
Soleil
  • 6,404
  • 5
  • 41
  • 61
  • 2
    You can't, because C++ simply does not work this way. And even `&B::SomeJob` won't work either, because it wouldn't be a function pointer, because `SomeJob()` is not a function. It is a class method. Big difference. See your C++ book for more information. – Sam Varshavchik Mar 26 '20 at 02:04
  • 1
    C++ solutions to problems generally don't involve slinging function pointers around, it's not a functional programming language. Consider using a template. – tadman Mar 26 '20 at 02:15
  • @SamVarshavchik I can store a lambda. – Soleil Mar 26 '20 at 02:15
  • 1
    In C++ don't have multiple functions you pick from, have multiple subclasses that implement it differently with `virtual` functions and let C++ do the work for you. What you're proposing is re-inventing class inheritance, but doing it in a clunky way. There's dozens of [design patterns](https://en.wikipedia.org/wiki/Software_design_pattern) that can solve this and they don't need function pointers. – tadman Mar 26 '20 at 02:16
  • 1
    @Soleil That's better! Have you looked at `Qt` (I'm not saying it's good)? – Ted Lyngmo Mar 26 '20 at 02:16
  • You need to pass the `B` object to `B::SomeJob`. You have to pass it some way. – L. F. Mar 26 '20 at 02:19
  • After more careful debugging, I saw that the lambda actually works fine at runtime. – Soleil Mar 26 '20 at 12:57
  • The lambda should probably use `[=]` or `[someB]`, not `[&]`. Putting a lambda which captures anything by reference into a `std::function` is a very dangerous thing, since the referenced object captured will usually be long gone when the lambda is later called. – aschepler Sep 10 '20 at 22:25

1 Answers1

1

Function pointer to a non static class member method cannot be typecasted to normal non-class--method function pointer. If done, it's an undefined behaviour and most certainly results in crash.
The reason is that, an object of that class is required to invoke it's method.

Your conventional pointer to member syntax is better.

Refer:

iammilind
  • 68,093
  • 33
  • 169
  • 336
  • Can you please reopen the question? Storing a lambda in function actually works fine, and that's exactly that answer I want. – Soleil Mar 26 '20 at 13:00
  • @Soleil, it's dangerous, as the object may or nay not exist when the lambda us actually invoked. So pass by reference must be avoided in this case. Pass by value makes a local copy, so useless. Just compilation doesn't solve the problem. Can you kindly flag to moderation for reopen. I am not sure, if your question is unique from the other posts, I linked in my answer. – iammilind Mar 28 '20 at 01:19
  • We can add further code to address the non-existence case, in my case, it is know to exists. I voted for reopen; my situation is different; I may further develop in which way. – Soleil Mar 28 '20 at 13:57