Home > front end >  c - access pointer to call method (using callbacks etc)
c - access pointer to call method (using callbacks etc)

Time:12-22

I am trying to figure out how to do this. I have 2 classes -

class Caller(){
//constructs Callee

    void onEventFired(){
        //need to call a function on an obj
        //which I dont have access to here

        //objptr->funcA
    }
};

class Callee(){
//it has access to an instance of caller object
private:
    void setup(){
        std::unique_ptr objptr = make_unique<SampleClass>....
        //create unique ptr of obj

        //can pass the objptr to Caller through a
        //separate function but probably not clean ??
    }
};

Chain of events - Caller creates the callee instance during its own construction, – later, callee's setup function is called which creates SampleClass pointer. at some point later, the periodic event starts to fire up thats when I want call SampleClass's funcA from within Caller

One way is to pass the raw SampleClass pointer to the Caller class through a separate function but ideally I don't want the class Caller to have access to that. Is there a way using some callbacks which I can do this cleanly.

CodePudding user response:

Your question is a little weak in motivation, so let's beef it up just a tad.

Suppose that Caller accepts registrations for things that want to be called back whenever EVENT_FIRED happens. So, the system has something like this:

    //... initialize all callees
    //... wait for event
    switch (event) {
    //...
    case EVENT_FIRED:
        //...
        //callback all interested callees
        Caller::instance().onEventFired();
        break;
    //...
    default:
        //...
        break;
    };

Typically, you will want the callees to register themselves with the Caller instance, so that they get notification of the event via their registered callback.

In order to accept registrations, you would use some kind of container in the caller to track them.

class Caller {
public:
    struct Callback {
        virtual ~Callback () = default;
        virtual void fire () = 0;
    };

    static Caller & instance () {
        static Caller one;
        return one;
    }

    template <typename CALLBACK, int EVENT>
    void subscribe () {
        std::unique_ptr<Callback> cb(std::make_unique<CALLBACK>());
        callbacks_[EVENT].push_back(std::move(cb));
    }

    //...
    void onEventFired () {
        for (auto &cb : callbacks_[EVENT_FIRED]) cb->fire();
    }

private:
    typedef std::list<std::unique_ptr<Callback>> CallbackList;

    std::unordered_map<int, CallbackList> callbacks_;

    Caller () = default;
    Caller (const Caller &) = delete;
    Caller & operator = (Caller) = delete;
    ~Caller () = default;
};

The Caller now implements the Callback interface, and makes its registration during setup.

class Callee : public Caller::Callback {
public:
    static void setup () {
        Caller::instance().subscribe<Callee, EVENT_FIRED>();
    }
    void fire () { std::cout << "You're fired!\n"; }
};

Try it online!

CodePudding user response:

Here are 2 references may be what you're looking for. The Attorney-Client idiom, and pass-key pattern.

The Attorney-Client idiom is a method that add a proxy class. The proxy class is a friend of the class which needs access. [Callee] - [Proxy] - [Caller] relationship is built.

Pass-Key pattern is a relatively simple method to solve the problem. The main idea is same that uses friend keyword. However, it's using class template, rooted in template meta programming. For more sophisticated usage, take a look at this version. (the last answer)

  • Related