vendredi 21 avril 2017

C++: How to store various member functions of different classes for later use

thanks in advance for your support.

I'm using C++11 and I want to store public member functions of some classes for later use as callback functions; e.g. I want to store some functions that matches this template: void(classname::*)(void). As far as I know, I have to store their objects too, It's fine. For example:

// PSEUDO CODE
class A {
    public:
    void myfunc() {}
}myobj;

class B {
    public:
    void myfunc2() {}
}myobj2;

/* storing */
mystorageclass storage;
storage.push(&myobj, &A::myfunc);
storage.push(&myobj2, &B::myfunc2);

/* call them back */
(storage[0].object->*(storage[0].callback))();
(storage[1].object->*(storage[1].callback))();

Is there any safe and generic way to do that? Actually I've found a way, but I'm not sure how much it's portable across processors or compilers.

//test.cpp - compiled with: g++ test.cpp -o test -std=c++11
#include <iostream>
#include <vector>

class A {
    public:
    void myfunc() { std::cout << "Test A::myfunc()" << std::endl; }
}myobj;

class B {
    public:
    void myfunc2() { std::cout << "Test B::myfunc2()" << std::endl; }
}myobj2;

struct Callback {
    void* object;
    void(* method)(void*);
};

std::vector<Callback> callbackList;

template<typename FunctionPtr>
void add(void* object, FunctionPtr fptr) {
    Callback cb;
    cb.object = object;
    cb.method = (void(*)(void*))(*(void**)(&fptr));
    callbackList.push_back(cb);
}

int main() {
    //add to list for later use
    add(&myobj, &A::myfunc);
    add(&myobj2, &B::myfunc2);

    //call them back
    callbackList[0].method(callbackList[0].object);
    callbackList[1].method(callbackList[1].object);
}

And another way to do; I feel this is much more safe:

//test2.cpp - compiled with: g++ test2.cpp -o test2 -std=c++11
#include <iostream>
#include <vector>

class A {
    public:
    void myfunc() { std::cout << "Test A::myfunc()" << std::endl; }
}myobj;

class B {
    public:
    void myfunc2() { std::cout << "Test B::myfunc2()" << std::endl; }
}myobj2;

struct Callback {
    struct A;
    A* object;
    void(A::* method)();
    void call() {
        (object->*method)();
    }
};

std::vector<Callback> callbackList;

template<typename FunctionPtr>
void add(void* object, FunctionPtr fptr) {
    Callback cb;
    cb.object = (Callback::A*)object;
    cb.method = (void(Callback::A::*)())(fptr);
    callbackList.push_back(cb);
}

int main() {
    //add to list for later use
    add(&myobj, &A::myfunc);
    add(&myobj2, &B::myfunc2);

    //call them back
    callbackList[0].call();
    callbackList[1].call();
}

Does these usages are safe? Or what do you suggest instead of these. Thanks.

Aucun commentaire:

Enregistrer un commentaire