【问题标题】:c++ inject function in classc++ 在类中注入函数
【发布时间】:2016-05-21 20:45:33
【问题描述】:

我有这个基类:

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; }
};

还有一个用这个方法实现Task的类:

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();

}

main():

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

这可行,但我想知道如何访问 t3 实例的私有(和公共)成员;类似:

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

简而言之,我想在一个类中注入一个函数,并在其中使用它的类成员。

【问题讨论】:

  • Task::high中调用函数时,为什么不将成员值作为参数传递给函数?
  • 听起来LedTask 继承自Task,那么为什么不在Task 中简单地使用一个在callFoo() 中调用的纯virtual 函数呢?真的不需要 lambda。
  • @πάντα ῥεῖ,嗨;这个想法是拥有相同的 LedTask 类实现,但每次我需要时都改变他的行为。即我希望创建两个 LedTask(一个用于引脚 13,一个用于引脚 3)一个开关他自己的导致关闭另一个开关导致打开(这只是一个例子:))。我虽然为了实现这种行为,我可以用 lambda 注入函数体。
  • @edoz90 你是否真的需要一个 lambda 是值得怀疑的,但好吧......

标签: c++ class lambda private


【解决方案1】:

正如我在评论中提到的,我想您的 LedTask 类继承自 Task

因此,您应该将函数指针放在Task 类中,转而使用纯virtual 函数,该函数必须在继承类中实现:

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; }
};

然后在LedTask 的第二步中基于std::function 构造函数参数实现foo

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_;
};

好吧,从您的 cmets 看来,您需要 Led 对象作为注入函数的参数。

init() 中创建的Led 的成员指针应传递给注入函数。

你可以使用类似的东西

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

    void(*f_)(Led&);

传递该参数是在上面的实现中完成的:

    void foo() {
        f_(*led);
    }

【讨论】:

  • 我的环境 (Arduino) 没有 std::function 的功能标头,我应该使用 void (*f)() 吗?我不明白 LedTask 构造函数的语法。编辑:无论如何感谢您的帮助。
  • @edoz90 This 可能会稍微澄清一下使用的语法。对于这种简单的情况,您实际上可能不需要使用std::function,而是使用一个普通的函数指针。关键是,我不会在 Task 基类的级别上这样做。
  • 如何使用构造函数访问或调用LedTask自带的变量和方法?
  • @edoz90 我不明白你的问题?你的意思是要指定LedTask的成员函数?您可以提供publicstatic 成员函数和LedTask,可以选择用于构造。但是还有很多其他方法可以完全不用函数指针来解决这个问题。
  • @edoz90 " 它可以工作,但不是我想要实现的目标" 好吧,你不能从公共范围内访问任何私有成员,期间。使用minimal reproducible example 在您的问题中明确您想要实现的目标。
猜你喜欢
  • 2019-04-08
  • 1970-01-01
  • 1970-01-01
  • 2011-01-02
  • 1970-01-01
  • 2017-10-21
  • 1970-01-01
  • 2013-01-30
  • 2011-12-27
相关资源
最近更新 更多