1

I've this base class:

class Task {
private:
    bool enabled;
    void (*foo)();
public:
    virtual void init(int period) { enabled = true; }
    virtual void tick() = 0;

    void high(void (*f)()) { foo = f; }

    void callFoo() { foo(); }

    bool isEnabled() { return enabled; }
};

and a class which implements Task with this method:

LedTask::LedTask(int pin, Context* pContext) {
    this->pin = pin;
    this->pContext = pContext;
}

void LedTask::init(int period) {
    Task::init(period);
    this->led = new Led(pin);
}

void LedTask::tick() {
    Task::callFoo();

}

in main():

Task* t3 = new LedTask(LED_PIN, c);
t3->init(50);
t3->high([]{Serial.println("ok");});

This works but I'd like to know how to access private (and public) member of t3 instance; something like:

t3->high([]{ led->switchOn(); });

In short, I want to inject a function in a class and use its class members in it.

notdodo
  • 149
  • 2
  • 15
  • Why don't you pass the member values as parameters to the function when invoking it in `Task::high`? – Dan Mašek May 21 '16 at 20:50
  • Sounds like `LedTask` inherits from `Task`, so why not simply use a pure `virtual` function in `Task` that's called in `callFoo()`? There's not really a need for a lambda. – πάντα ῥεῖ May 21 '16 at 20:50
  • 1
    @πάντα ῥεῖ, hi; the idea is to have the same LedTask class implementation but change his behaviour every time I need to. i.e. I wish to create two LedTask (one for pin 13, one for pin 3) one switch his own led to off the other one switch the led to on (it's a just an example :) ). I though that to achieve this behaviour I could inject the body of a function with a lambda. – notdodo May 21 '16 at 21:02
  • @edoz90 It's questionable if you actually need a lambda here, but well ... – πάντα ῥεῖ May 21 '16 at 21:57

1 Answers1

1

As mentioned in my comment I suppose your LedTask class inherits from Task.

So you should drop the function pointer in the Task class in favor of a pure virtual function, that must be implemented in the inheriting classes:

class Task {
private:
    bool enabled;
protected: 
    virtual void foo() = 0; // <<<<<<<<<<<<<<<<<<<<<<<<<<
public:
    virtual void init(int period) { enabled = true; }
    virtual void tick() = 0;

    // void high(void (*f)()) { foo = f; } << not needed

    void callFoo() { foo(); }

    bool isEnabled() { return enabled; }
};

then in a second step in LedTask implement foo based on a std::function constructor parameter:

class LedTask : public Task {
public:
    LedTask(uint8_t pin, Context* pContext , std::function<void()> f) 
    : pin_(pin), pContext_(pContext), f_(f) {
    }
private:
    void foo() {
        f_();
    }
    uint8_t pin_;
    Context* pContext_;
    std::function<void()> f_;
};

Well, from your comments it sounds you'll need the Led object as a parameter for your injected function.

That member pointer for Led created in init() should be passed to the injected function.

You can either use something like

    std::function<void(Led&)> f_;

or

    void(*f_)(Led&);

Passing that parameter is done in the implementation as from above:

    void foo() {
        f_(*led);
    }
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • my environment (Arduino) do not have functional header for std::function, should I use void (*f)()? I don't understand the syntax of LedTask constructor. EDIT: anyway thanks for the help. – notdodo May 21 '16 at 21:22
  • @edoz90 [This](http://stackoverflow.com/questions/1711990/what-is-this-weird-colon-member-syntax-in-the-constructor) might clarify the syntax used a bit. For that simple case you might not actually need to use `std::function`, but get off with a plain function pointer. The point is, I wouldn't do that at the level of the `Task` base class. – πάντα ῥεῖ May 21 '16 at 21:39
  • how can I use the constructor to access or call LedTask own variables and methods? – notdodo May 21 '16 at 21:44
  • @edoz90 I don't get your question? You mean you want to specify a member function of `LedTask`? You can provide `public` `static` member functions with `LedTask` that can be selected for construction. But there are many other ways to solve that without function pointers at all. – πάντα ῥεῖ May 21 '16 at 21:45
  • Sorry :) I'll try to explain it better: in `LedTask` I create a `led` object in `init` func (see `LedTask` code in question above); is it possible to interact with this object from the `f_` function? If yes, how? – notdodo May 21 '16 at 21:51
  • @edoz90 Provide `Led` as another parameter to `f_`? -> `std::function f_;` Or as the raw function pointer definition: `void(*f_)(Led& led);` – πάντα ῥεῖ May 21 '16 at 21:54
  • I think that I do not have explain it clearly...what do you suggest is correct and it works but is not what I want to achieve. Maybe I've to change approach... Anyway, thanks for your time and thanks for show me some useful stuff. – notdodo May 21 '16 at 22:38
  • 1
    @edoz90 _" and it works but is not what I want to achieve"_ Well, you cant access any private members from public scope, period. Make it clear in your question with a [MCVE] what you want to achieve. – πάντα ῥεῖ May 21 '16 at 22:42