Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call C++ member function pointer without knowing which class

I am trying to call a member function, possibly given the object pointer, without knowing what class the member function is from. Is this possible?

Basically I want something like the following to work.

class Foo{
public:
    Foo(void* object): obj(object) {}

    void callFunc(void (*func)()){
        obj->*func();
    }

private:
    void* obj;
};

class Bar{
public:
    Bar(): foo(this) {}

    void callSomeFunc(){
        callFunc(someFunc);
    }

    void someFunc(){
        cout << "hi\n";
    }

private:
    Foo foo;
};

int main(){
    Bar bar;
    bar.callSomeFunc();
    return 0;
}
like image 714
Bennett Bernardoni Avatar asked Aug 14 '17 20:08

Bennett Bernardoni


2 Answers

It looks a lot like an XY-problem. Anyway, let's try to reply to your question as it is.

A function member is bound to the type of the class to which it belongs, unless it's a static one (the latter is treated just like a plain function pointer and you don't even have to pass a pointer to an instance to call it).
Therefore you can make callFunc a function template and let it deduce the type for you:

template<typename T>
void callFunc(void (T::*func)()){
    (static_cast<T*>(obj)->*func)();
}

See it up and running on wandbox.

Note that you can incur in errors when you static_cast your obj if its original type (the one you erased to put it in a void *) isn't T.


Here is the full code you can see at the link above:

#include<iostream>

class Foo{
public:
    Foo(void* object): obj(object) {}

    template<typename T>
    void callFunc(void (T::*func)()){
        (static_cast<T*>(obj)->*func)();
    }

private:
    void* obj;
};

class Bar{
public:
    Bar(): foo(this) {}

    void callSomeFunc(){
        foo.callFunc(&Bar::someFunc);
    }

    void someFunc(){
        std::cout << "hi\n";
    }

private:
    Foo foo;
};

int main(){
    Bar bar;
    bar.callSomeFunc();
    return 0;
}
like image 108
skypjack Avatar answered Sep 18 '22 16:09

skypjack


It's an XY problem. Use a std::function and/or a lambda.

#include <functional>
#include <iostream>

class Foo{
public:
    template<class F>
    void callFunc(F&& f){
        f();
    }
};

class Bar : public Foo{
public:
    Bar(): foo() {}

    void callSomeFunc(){
        this->callFunc([this]{ someFunc(); });
    }

    void someFunc(){
        std::cout << "hi\n";
    }

private:
    Foo foo;
};

int main(){
    Bar bar;
    bar.callSomeFunc();
    return 0;
}
like image 30
Richard Hodges Avatar answered Sep 17 '22 16:09

Richard Hodges