不使用 std::bind、std::function 或 boost 的 C++ 多成员函数回调
C++ multiple member function callbacks without using std::bind, std::function or boost
我有一个应用程序需要一个对象的一个或多个成员函数在监视对象中发生硬件事件时用作回调。回调不需要参数。
通常我会使用 boost 或标准库函数(std::function,std::bind)来包装要调用的成员函数,但我不能像它们那样使用它们(boost,C++11)平台不支持或不允许。我也不确定效率,但那是题外话。
简而言之,我编写了 class (MonitorSwi),它生成一个线程来等待硬件事件。创建对象时将配置硬件事件和回调,以便许多其他对象(例如下面的 DeviceManager)可以利用此封装功能。
除了使用 bind 之外,另一种方法是让基 class 具有由子对象实现的纯虚拟处理程序。然而,一些 'DeviceManagers' 处理需要不同处理程序的多个 SWI。
我目前使用的方法是让一个静态成员重定向到特定对象实例和指定的 SWI 处理程序。
我写了一个简单的例子,去掉了所有不必要的代码:
#include <iostream>
class MonitorSwi
{
public:
typedef void (*SwiHandlerFunc_t)(void*);
MonitorSwi(int id, void* pInstance, SwiHandlerFunc_t handler) :
m_id(id),
m_instance(pInstance),
m_handler(handler)
{
}
void HandleEvent()
{
std::cout << "MonitorSwi::HandleEvent() Handle SWI ID = " << m_id << std::endl;
(*m_handler)(m_instance);
}
private:
int m_id;
void* m_instance;
SwiHandlerFunc_t m_handler;
};
class DeviceManager
{
public:
DeviceManager() :
m_Swi1(1, this, HandleSwi1), // Register handler for SWI 1 events
m_Swi2(2, this, HandleSwi2) // Register handler for SWI 2 events
{
}
static void HandleSwi1(void* pInstance)
{
std::cout << "DeviceManager::HandleSwi1() Redirect to object..." << std::endl;
DeviceManager* ptr = reinterpret_cast<DeviceManager*>(pInstance);
ptr->HandleSwi1Member();
}
static void HandleSwi2(void* pInstance)
{
std::cout << "DeviceManager::HandleSwi2() Redirect to object..." << std::endl;
DeviceManager* ptr = reinterpret_cast<DeviceManager*>(pInstance);
ptr->HandleSwi2Member();
}
void HandleSwi1Member()
{
std::cout << "DeviceManager::HandleSwi1Member()" << std::endl;
// Process event that SWI 1 has signalled...
}
void HandleSwi2Member()
{
std::cout << "DeviceManager::HandleSwi2Member()" << std::endl;
// Process event that SWI 2 has signalled...
}
MonitorSwi m_Swi1;
MonitorSwi m_Swi2;
};
int main()
{
DeviceManager device;
// Fake hardware calling SWI 1 (normally performed by hardware event handler)
device.m_Swi1.HandleEvent();
// Fake hardware calling SWI 2 (normally performed by hardware event handler)
device.m_Swi2.HandleEvent();
return 0;
}
测试应用程序的输出:
MonitorSwi::HandleEvent() Handle SWI ID = 1
DeviceManager::HandleSwi1() Redirect to object...
DeviceManager::HandleSwi1Member()
MonitorSwi::HandleEvent() Handle SWI ID = 2
DeviceManager::HandleSwi2() Redirect to object...
DeviceManager::HandleSwi2Member()
我确定一定有一种方法可以使用模板来指定 class 类型以及在该 class 类型中声明的一个或多个成员函数处理程序。
是否有更有效或更通用的方法来实现上述目标?
您可以简单地存储
typedef void (T::*SwiHandlerFunc_t)();
(对于类型 T
作为 MonitorSwi<T>
的模板参数)并通过
调用它
(m_instance->*m_handler)();
完整代码在live example.
我有一个应用程序需要一个对象的一个或多个成员函数在监视对象中发生硬件事件时用作回调。回调不需要参数。
通常我会使用 boost 或标准库函数(std::function,std::bind)来包装要调用的成员函数,但我不能像它们那样使用它们(boost,C++11)平台不支持或不允许。我也不确定效率,但那是题外话。
简而言之,我编写了 class (MonitorSwi),它生成一个线程来等待硬件事件。创建对象时将配置硬件事件和回调,以便许多其他对象(例如下面的 DeviceManager)可以利用此封装功能。
除了使用 bind 之外,另一种方法是让基 class 具有由子对象实现的纯虚拟处理程序。然而,一些 'DeviceManagers' 处理需要不同处理程序的多个 SWI。
我目前使用的方法是让一个静态成员重定向到特定对象实例和指定的 SWI 处理程序。
我写了一个简单的例子,去掉了所有不必要的代码:
#include <iostream>
class MonitorSwi
{
public:
typedef void (*SwiHandlerFunc_t)(void*);
MonitorSwi(int id, void* pInstance, SwiHandlerFunc_t handler) :
m_id(id),
m_instance(pInstance),
m_handler(handler)
{
}
void HandleEvent()
{
std::cout << "MonitorSwi::HandleEvent() Handle SWI ID = " << m_id << std::endl;
(*m_handler)(m_instance);
}
private:
int m_id;
void* m_instance;
SwiHandlerFunc_t m_handler;
};
class DeviceManager
{
public:
DeviceManager() :
m_Swi1(1, this, HandleSwi1), // Register handler for SWI 1 events
m_Swi2(2, this, HandleSwi2) // Register handler for SWI 2 events
{
}
static void HandleSwi1(void* pInstance)
{
std::cout << "DeviceManager::HandleSwi1() Redirect to object..." << std::endl;
DeviceManager* ptr = reinterpret_cast<DeviceManager*>(pInstance);
ptr->HandleSwi1Member();
}
static void HandleSwi2(void* pInstance)
{
std::cout << "DeviceManager::HandleSwi2() Redirect to object..." << std::endl;
DeviceManager* ptr = reinterpret_cast<DeviceManager*>(pInstance);
ptr->HandleSwi2Member();
}
void HandleSwi1Member()
{
std::cout << "DeviceManager::HandleSwi1Member()" << std::endl;
// Process event that SWI 1 has signalled...
}
void HandleSwi2Member()
{
std::cout << "DeviceManager::HandleSwi2Member()" << std::endl;
// Process event that SWI 2 has signalled...
}
MonitorSwi m_Swi1;
MonitorSwi m_Swi2;
};
int main()
{
DeviceManager device;
// Fake hardware calling SWI 1 (normally performed by hardware event handler)
device.m_Swi1.HandleEvent();
// Fake hardware calling SWI 2 (normally performed by hardware event handler)
device.m_Swi2.HandleEvent();
return 0;
}
测试应用程序的输出:
MonitorSwi::HandleEvent() Handle SWI ID = 1
DeviceManager::HandleSwi1() Redirect to object...
DeviceManager::HandleSwi1Member()
MonitorSwi::HandleEvent() Handle SWI ID = 2
DeviceManager::HandleSwi2() Redirect to object...
DeviceManager::HandleSwi2Member()
我确定一定有一种方法可以使用模板来指定 class 类型以及在该 class 类型中声明的一个或多个成员函数处理程序。
是否有更有效或更通用的方法来实现上述目标?
您可以简单地存储
typedef void (T::*SwiHandlerFunc_t)();
(对于类型 T
作为 MonitorSwi<T>
的模板参数)并通过
(m_instance->*m_handler)();
完整代码在live example.