C++ 方法作为从另一个类的回调

C++ 方法作为从另一个类的回调,c++,avr,C++,Avr,我将尽可能简单地描述我的问题 我的问题是: 我的第一堂课是单身: class CTimer1 { public: static CTimer1 * getInstance(); //This gives me pointer to instance void setChannelA(uint8_t compareValue); private: //Cnstructors CTimer1(); //Prevent consttuction but a

我将尽可能简单地描述我的问题

我的问题是:

我的第一堂课是单身:

class CTimer1
{
public:
    static CTimer1 * getInstance();       //This gives me pointer to instance
    void setChannelA(uint8_t compareValue);
private:
    //Cnstructors
    CTimer1();  //Prevent consttuction but allow in getInstance
    CTimer1(const CTimer1&);    //Prevent construction by copying
    CTimer1& operator=(const CTimer1&); //Prevent assigment
    ~CTimer1();                 //Prevent unwanted destruction
    static CTimer1 * timerInstance;
    static bool isCreated;
};
这里是第二个类,我希望能够从CTimer1类调用setChannelA方法,作为从CServo类调用setPwm方法:

以下是registerPwmTimer方法:

然后,我尝试将指针分配给此方法,如下所示:

int main()
{   
    CTimer1 * timer1 = CTimer1::getInstance();
    CServo servo1();
    servo1.registerPwmTimer(timer1->setChannelA);
    servo1.setPwm(10);       //This is example how I want to call setChannelA method

    while(1)
    {

    }
}
我有一个错误:

error: no matching function for call to 'CServo::registerPwmTimer(<unresolved overloaded function type>)'
重要的是:


我不能使用STD::For函数,因为这是C++中嵌入设备的代码的一部分,所以我需要节省内存消耗。我有没有办法达到这个效果?如果只有一种方法可以做到这一点,那就是不要使用std库,也请提供答案。谢谢您的帮助。

您的问题是函数指针必须指向静态函数。当您调用一个实例函数或方法时,会有一个隐藏的第一个参数,该参数是调用该函数的对象。此隐藏参数在函数定义中可用

您的CServo::registerPwmTimer函数签名与成员函数的调用不兼容;函数指针本身不提供将参数绑定到指针的方法,因此即使可以使用自由函数指针类型传递成员函数指针,在调用函数指针时也无法确定隐藏的此参数

换言之,它将失败,原因与尝试CTimer1::setChannelA0失败的原因相同——您希望调用该方法,但尚未告知要调用该方法的对象

将CServo::registerPwmTimer的签名更改为接受对象而不是原始函数指针。函数对象可以从函数指针构造,但也可以从lambdas构造,一些标准库函数返回函数对象:

void registerPwmTimer(std::function<void(uint8_t)>);
请注意,std::bind不会延长timer1指向的对象的生存期。如果在销毁该对象后调用返回的函数,则结果是未定义的行为

另一种选择是接受实例和指向成员函数的指针。这种方法的问题在于它需要使用模板:

template <typename T>
void registerPwmTimer(void (T::*)(uint8_t), T&);
现在我们有了一个函数指针类型,它也可以与指向函子的指针一起使用:

template <typename T>
class fn_poly_callable : public poly_callable
{
public:
    typedef T fn_type;

    fn_poly_callable(T);
    virtual void operator()(int) const;

private:
    T fn;
};
另外,我们还需要一些帮助函数来允许编译器推断模板类型。一个用于函数指针:

template <typename T>
std::unique_ptr<poly_callable> make_poly_callable(T fn)
{
    return std::unique_ptr<poly_callable>(new fn_poly_callable<T>(fn));
}
如果你想看到这一切,我做了一个决定


所以。。。只需使用std::函数。没有理由重新发明这种东西。

您必须使void setChannelAuint8\u t compareValue函数静态,或者将void registerPwmTimervoid*callbackuint8\u t u8\u buffer更改为void registerPwmTimervoid*CTimer1::mem\u fun\u callbackuint8\u u8\u buffer,CTimer&obj因为非静态成员函数没有相应的对象,所以没有意义,因为成员函数在内部使用此指针。无效注册表rWMTimerVOID CTimer1::*mem_fun_callbackuint8_t u8_u u u buffer,CTimer&obj是正确的成员函数指针声明您也可以使用std::function而不是函数指针类型。然后调用方可以使用lambda语法或std::bind&CTimer1::setChannelA,timer1将对timer1对象的引用绑定到回调。但是注意,如果在Time1被破坏后调用回调,结果是未定义的行为。@ EM2ER,只要回调是C++函数,没有外部C声明,就不需要使用静态成员函数。你真棒!现在我开始明白这是怎么回事了。祝您有个美好的一天!这就是我真正需要的。
template <typename T>
void registerPwmTimer(void (T::*)(uint8_t), T&);
class poly_callable
{
public:
    virtual void operator()(int) const = 0;
};
template <typename T>
class fn_poly_callable : public poly_callable
{
public:
    typedef T fn_type;

    fn_poly_callable(T);
    virtual void operator()(int) const;

private:
    T fn;
};
template <typename T, typename M = void (T::*)(int)>
class member_poly_callable : public poly_callable
{
public:
    typedef T object_type;
    typedef M member_fn_type;

    member_poly_callable(member_fn_type, object_type&);
    virtual void operator()(int) const;

private:
    member_fn_type mfn;
    object_type& target;
};
template <typename T>
std::unique_ptr<poly_callable> make_poly_callable(T fn)
{
    return std::unique_ptr<poly_callable>(new fn_poly_callable<T>(fn));
}
template <typename T>
std::unique_ptr<poly_callable> make_poly_callable(void (T::*mfn)(int), T& target)
{
    return std::unique_ptr<poly_callable>(new member_poly_callable<T>(mfn, target));
}

template <typename T>
std::unique_ptr<poly_callable> make_poly_callable(void (T::*mfn)(int) const, T& target)
{
    return std::unique_ptr<poly_callable>(new member_poly_callable<T, void (T::*)(int) const>(mfn, target));
}