Call a pointer to a function of a C ++ element without knowing which class

I am trying to call a member function, possibly pointing to a pointer to an object, not knowing which class the member function belongs to. Is it 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;
}
+4
source share
3 answers

It is very similar to the XY problem. In any case, try to answer your question as it is.

, , ( , , ).
callFunc :

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

wandbox.

, , static_cast obj, (, , void *), T.


, :

#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;
}
+4

XY. std::function / .

#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;
}
+1

Although I found the solution provided by @skypjack to be more elegant, here is a solution that templates the Foo-class (and not just the "function") as a whole. Thus, a type objis known throughout the class Foo, which may be an advantage (or may be absent).

Further, see also the solution that stores the element along with the associated object. Maybe this is useful in some way:

#include <functional>
#include <iostream>


template<class T>
class Foo {
public:
    Foo(T& obj) : _obj(obj) {}

    void callFuncOnObj(void (T::*func)(void)) {
        auto fn = mem_fn(func);
        fn(_obj);
    }

private:
    T &_obj;
};

class Bar{
public:
    Bar() : d(*this) {}

    void callSomeFunc(){
        d.callFuncOnObj(&Bar::someFunc);
    }

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

private:
    Foo<Bar> d;
};

class Foo2 {
public:
    Foo2(std::function<void(void)> f) : _f(f) {}

    void callFunction() {
        _f();
    }

private:
    std::function<void(void)> _f;
};

class Bar2{
public:
    Bar2() : d(std::bind(&Bar2::someFunc,this)) {}

    void callSomeFunc(){
        d.callFunction();
    }

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

private:
    Foo2 d;
};


int main(){

    Bar bar;
    bar.callSomeFunc();

    Bar2 bar2;
    bar2.callSomeFunc();

    return 0;
}
0
source

Source: https://habr.com/ru/post/1683709/


All Articles