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