将一个对象的成员函数作为回调函数存储在另一个对象中
Storing member function of an object as a callback function in another object
我是回调函数的新手。我写了一节Timer
课。它将回调函数存储在其中,并在它们各自的周期后回调它们。
计时器.h
#ifndef UTILITY_CLASSES__TIMER_H
#define UTILITY_CLASSES__TIMER_H
#include <stdint.h>
#include <list>
#include <Windows.h>
class Timer
{
public:
static uint64_t LAST_TIMER_ID;
uint64_t TimerId;
uint64_t KillId;
typedef void (*TimerCallBackFunction) (DWORD, uint64_t);
Timer(UINT Period, TimerCallBackFunction CbFunction);
~Timer();
protected:
class TimerInfo
{
public:
TimerInfo(TimerCallBackFunction Cbf, uint64_t Tid, uint64_t Kid)
: Callback(Cbf), TimerId(Tid), KillId(Kid) {}
TimerCallBackFunction Callback;
uint64_t TimerId;
uint64_t KillId;
};
static VOID CALLBACK TimerProc( _In_ HWND hwnd,
_In_ UINT uMsg,
_In_ UINT_PTR idEvent,
_In_ DWORD dwTime);
static std::list<TimerInfo> Timers;
};
#endif // UTILITY_CLASSES__TIMER_H
计时器.cpp
#include "Timer.h"
#include <Windows.h>
uint64_t Timer::LAST_TIMER_ID = 0;
Timer::Timer(UINT Period, TimerCallBackFunction CbFunction)
{
TimerId = ++LAST_TIMER_ID;
KillId = SetTimer(NULL, TimerId, Period, Timer::TimerProc);
if (KillId == NULL)
{
LAST_TIMER_ID--; // roll back
TimerId = 0;
}
else
{
Timers.push_back(TimerInfo(CbFunction, TimerId, KillId));
}
}
Timer::~Timer()
{
for (std::list<TimerInfo>::const_iterator it=Timers.begin(); it!=Timers.end(); ++it)
{
if (it->TimerId == TimerId)
{
Timers.erase(it);
break;
}
}
}
VOID CALLBACK Timer::TimerProc( _In_ HWND hwnd,
_In_ UINT uMsg,
_In_ UINT_PTR idEvent,
_In_ DWORD dwTime)
{
for (std::list<TimerInfo>::const_iterator it=Timers.begin(); it!=Timers.end(); ++it)
{
if (it->TimerId == idEvent)
{
it->Callback(dwTime, it->TimerId);
break;
}
}
}
main.cpp
#include <Windows.h>
#include "Timer.h"
class MyClass
{
public:
void CallMe(DWORD Time, uint64_t TimerId)
{
MessageBoxW(NULL, L"Callback function is called!",
L"Notification", MB_ICONINFORMATION);
}
};
int APIENTRY wWinMain( _In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
_In_ int nCmdShow)
{
// ...
MyClass MyObject;
Timer TimerObject(10000, MyObject.CallMe); // Line 114
//...
return 0;
}
当我编译这个代码时,我收到了这个错误消息:
第114行
错误C3867:
"MyClass::CallMe":函数调用缺少参数列表;使用'&MyClass::CallMe'以创建指向成员的指针
当我在第114行将MyObject.CallMe
更改为&MyClass::CallMe
或&MyObject.CallMe
时,我无法运行代码。
我的代码做错了什么?
IDE:Microsoft Visual Studio 2012
文档:SetTimer、TimerProc
typedef void (*TimerCallBackFunction) (DWORD, uint64_t);
为指向自由函数的指针声明了一个typedef,而这些不能用于指向成员函数。您需要一个指向成员函数的指针:
typedef void (MyClass::*TimerCallBackFunction) (DWORD, uint64_t);
在进行typedef之前,您需要转发声明MyClass
,并执行错误消息所说的操作:
Timer TimerObject(10000, &MyObject::CallMe);
// ^^^^^^^^^^^^^^^^^
推荐阅读:C++FAQ-Lite上的成员函数指针部分。
我会使用std::function
而不是函数指针,然后使用带有占位符的std::bind
:
将typedef更改为
typedef std::function<void (DWORD, uint64_t)> TimerCallBackFunction;
在WinMain()
中,将std::function
绑定到实例MyObject
的CallMe()
,然后用两个参数替换占位符来调用该实例。
MyClass MyObject;
Timer TimerObject(10000, std::bind(&MyClass::CallMe,
MyObject,
std::placeholders::_1,
std::placeholders::_2));
相关文章:
- 如何使用函数将一个对象的输入复制到另一个对象中
- C++ - 使用另一个类的构造函数实例化一个对象
- 复制赋值函数如何访问另一个对象的私有成员(Stroustroup 原则和实践书)?
- 为什么数组中对象的析构函数在被另一个对象替换时不被调用?
- 如何创建一个对象创建函数,该函数将由与其关联的名称调用?
- C++将带有重载构造函数的对象添加到另一个对象
- 访问另一个类中的模板化嵌套类函数和对象
- 编译问题 C++ 同时,尝试通过调用另一个对象中的成员函数来创建 std:: 线程
- 当我们有纯虚函数时,如何煽动一个对象?
- 如何在 main 函数的一个对象中初始化两个类的值?C++
- 指针阵列在一个对象数组中函数
- 我如何在类上需要另一个构造函数的对象中声明一个对象
- 在堆栈上有一个对象,而不是在函数的整个生命周期内
- 在C++中,当没有为类声明构造函数时,如果我用参数构造一个对象会发生什么
- 为什么在 C++ 中,当对象包含在另一个对象中时,复制构造函数被调用两次
- 如何将一个对象作为另一个类构造函数的参数传递?
- C :将一个对象复制到构造函数中的另一个对象
- 如果我在析构函数中创建一个对象,会发生什么
- 用另一个对象作为构造函数中的参数创建对象
- 如何在另一个对象的构造函数中声明和创建对象?