一个类的方法作为回调
Method of one class as callback from another
我会尽可能地描述我的问题。
我的问题是什么:
我有一个单身人士:
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
方法为setPwm
方法的第二类,从CServo
类:
class CServo {
public:
CServo();
~CServo();
public:
//public methods
void registerPwmTimer(void (*callback)(uint8_t u8_buffer));
void (*setPwm)(uint8_t u8_buffer); //As this method I would like to call setChannelA from CTimer1 class
};
这是registerPwmTimer
方法:
void CServo::registerPwmTimer(void (*callback)(uint8_t u8_buffer))
{
setPwm = callback;
}
然后,我试图将指针分配给该方法的以下内容:
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::function
,因为这是嵌入式设备中C 中代码的某些部分,因此我需要节省内存消耗。有什么办法可以实现这一效果?如果一方面这样做的可能性是使用某些性病库,请也以获取答案。感谢您的帮助。
您的问题是功能指针必须指向静态功能。当您调用一个实例函数(方法)时,有一个隐藏的第一个参数,这是调用函数的对象。(此隐藏的参数可作为函数定义中的this
可用。)
您的CServo::registerPwmTimer()
功能签名与调用成员函数完全不相容;单独的功能指针不能提供将参数绑定到指针的方法,因此,即使您可以使用(免费)函数指针类型传达成员函数指针,也无法确定隐藏的this
参数在调用函数指针时。
换句话说,它会失败,因为尝试 CTimer1::setChannelA(0)
会失败 - 您想调用该方法,但是您尚未传达要调用哪个对象的方法。
更改CServo::registerPwmTimer
的签名以接受std::function
对象而不是原始功能指针。std::function
可以从函数指针构建对象,但也可以从lambdas构造,并且某些标准库函数返回函数对象:
void registerPwmTimer(std::function<void(uint8_t)>);
现在,您可以使用std::bind
创建一个将对象实例绑定到成员函数指针的新功能:
servo1.registerPwmTimer(std::bind(&CTimer1::setChannelA, timer1));
请注意,std::bind
不扩展 timer1
指向对象的寿命。如果在破坏该对象后调用返回的函数,则结果是未定义的行为。
另一种选择是接受实例和指向成员函数的指针。这种方法的问题在于它需要使用模板:
template <typename T>
void registerPwmTimer(void (T::*)(uint8_t), T&);
这本身并不糟糕,但是您将要做的是创建一个多态性包装器类,以便您可以将其与其他不共享相同T
的回调一起插入回调列表中。那时,您只是在重新创建std::function
,因为std::function
已经有目的是在可呼叫的事物周围成为多态性包装器。
说明自己实施多态性可调查包装器的混乱,这是一个非常轻的例子。我将显示一组此类类型的声明,并链接到示例实现。
这是基本类型,带有纯虚拟operator()
,用作调用操作。
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;
};
和一个用于成员函数的 - 哦,但是const
成员函数和非const
成员函数不可互换,因此我们需要一个额外的模板参数:
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));
}
成员功能的两个(const
和非const
):
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));
}
如果您想看到这一切,我做了一个"简单"且有效的示例。
所以...只需使用std::function
即可。没有理由重新发明这些东西。
- 处理影响跨不同线程共享对象的定时回调的最佳方法是什么?
- C++ - 如何在不静态的情况下将回调绑定到类方法?
- 使用回调函数从构造函数调用虚拟/派生方法的替代方法?
- 重写另一个方法 [C++] 使用的超类回调函数
- 将类方法设置为 OpenSSL 回调
- 具有指向方法回调的指针的通用回调模板类
- 如何将提升回调作为参数传递给方法?
- 带有类方法的 Cython 回调
- 为什么可以在没有实例变量的情况下访问静态回调方法中的静态成员变量?
- 回调方法显示错误,类型为"void(*)"的值不能用于初始化类型的实体
- 全局挂钩 DLL 仅在 C# 主窗口处于活动状态/前台时调用 C# 回调方法
- 实现此"on error, throw"回调的最佳方法是什么?
- 从触摸回调访问向量元素的方法时,不良访问错误
- 注册和调用 DLL 回调的正确方法是什么
- 一个类的方法作为回调
- 破坏vulkan以测试调试回调是否正确设置的好方法是什么
- 从异步启动的方法回调的最优雅方式
- 未知类方法回调,它接受 0 个参数并返回可转换为 int 的类型
- 使用 Rice 在 C++ 中构建 Ruby 扩展:如何将 Ruby 方法(回调)的指针传输到C++函数
- 从C函数回调vs从c++方法回调