从 C++ 中的另一个对象执行方法
Method execution from another object in C++
首先请允许我介绍一下我的 class 结构。我正在为 ARM 设备 (STM32) 设计一个小库,我想实现几个定义系统上可用的不同外设的对象。
class xGPIO : public Peripheral
{
public:
xGPIO();
xGPIO(GPIO_TypeDef * GPIOx1, uint16_t Pinx1);
virtual ~xGPIO();
void on(void);
void off(void);
private:
void xInitGPIO(void);
};
我的想法是实现一个名为 callback 的内部 public 函数,它设置下一个要在我的计时器对象上调用的函数。但是这个函数肯定是另一个 class 中定义的方法,我希望它从 xTimer 中执行。这里的行为,应该是每当 Timer 结束倒计时时,它应该调用程序员存储在 callBack 方法中的函数。
class xTimer : public Peripheral
{
public:
xTimer(TIM_TypeDef * tim);
virtual ~xTimer();
/* void callBack(void (*f)()); */
private:
void xInitTimer(void);
TIM_HandleTypeDef htim;
};
void xTimer::callBack(void (*f)())
{
f();
}
main.cpp下的代码如下:
int main(void)
{
mySYS->initialize(false);
xGPIO myGreenLed (GPIOB, GPIO_PIN_0);
/* Declare Timers. */
xTimer myTimer(TIM2);
// myTimer.callBack(myGreenLed.on);
}
关于如何解决这个问题的任何线索?有没有一种简单的方法可以在 C++ 程序上遵守该设计?
您正在使用 C 模式。 C++ 具有更强大的 std::function
。您的 xTimer::callBack
应定义为
void xTimer::callBack(std::function<void(void)> f) { f(); }
所以它可以被称为
myTimer.callBack([&](){myGreenLed.on()}); //using lambda
或
myTimer.callBack(std::bind(&xGPIO::on, &myGreenLed));
直接使用模板也可以不用std::function
:
template<class T>
class xTimer : public Peripheral
{
public:
xTimer(TIM_TypeDef * tim);
virtual ~xTimer();
void callBack(T &obj, void (*T::f)())
{
(obj.*f)();
}
private:
void xInitTimer(void);
TIM_HandleTypeDef htim;
};
并且可以像这样使用:
xTimer<xGPIO> myTimer(TIM2);
myTimer.callBack(myGreenLed, &xGPIO::on);
然后您将失去 std::function
的灵活性,并且它不适用于 std::bind
和 lambda,但获得了没有 allocation/deallocation 的优势。
模板也可以只在 callback
级别,但我想您实际上想要存储值并稍后调用它,那么您需要对存储进行模板化。
如果您调用的方法只是特定单一类型的成员(即总是 xGPIO
),那么您甚至不需要模板。
另请注意,如果您存储要稍后调用的对象实例,则必须确保该对象的生命周期保持不变,直到您需要调用它(或者您需要制作一个副本,使用 std::shared_ptr
ETC。)。这也适用于使用 std::function
和对象指针或 std::ref
.
首先请允许我介绍一下我的 class 结构。我正在为 ARM 设备 (STM32) 设计一个小库,我想实现几个定义系统上可用的不同外设的对象。
class xGPIO : public Peripheral
{
public:
xGPIO();
xGPIO(GPIO_TypeDef * GPIOx1, uint16_t Pinx1);
virtual ~xGPIO();
void on(void);
void off(void);
private:
void xInitGPIO(void);
};
我的想法是实现一个名为 callback 的内部 public 函数,它设置下一个要在我的计时器对象上调用的函数。但是这个函数肯定是另一个 class 中定义的方法,我希望它从 xTimer 中执行。这里的行为,应该是每当 Timer 结束倒计时时,它应该调用程序员存储在 callBack 方法中的函数。
class xTimer : public Peripheral
{
public:
xTimer(TIM_TypeDef * tim);
virtual ~xTimer();
/* void callBack(void (*f)()); */
private:
void xInitTimer(void);
TIM_HandleTypeDef htim;
};
void xTimer::callBack(void (*f)())
{
f();
}
main.cpp下的代码如下:
int main(void)
{
mySYS->initialize(false);
xGPIO myGreenLed (GPIOB, GPIO_PIN_0);
/* Declare Timers. */
xTimer myTimer(TIM2);
// myTimer.callBack(myGreenLed.on);
}
关于如何解决这个问题的任何线索?有没有一种简单的方法可以在 C++ 程序上遵守该设计?
您正在使用 C 模式。 C++ 具有更强大的 std::function
。您的 xTimer::callBack
应定义为
void xTimer::callBack(std::function<void(void)> f) { f(); }
所以它可以被称为
myTimer.callBack([&](){myGreenLed.on()}); //using lambda
或
myTimer.callBack(std::bind(&xGPIO::on, &myGreenLed));
直接使用模板也可以不用std::function
:
template<class T>
class xTimer : public Peripheral
{
public:
xTimer(TIM_TypeDef * tim);
virtual ~xTimer();
void callBack(T &obj, void (*T::f)())
{
(obj.*f)();
}
private:
void xInitTimer(void);
TIM_HandleTypeDef htim;
};
并且可以像这样使用:
xTimer<xGPIO> myTimer(TIM2);
myTimer.callBack(myGreenLed, &xGPIO::on);
然后您将失去 std::function
的灵活性,并且它不适用于 std::bind
和 lambda,但获得了没有 allocation/deallocation 的优势。
模板也可以只在 callback
级别,但我想您实际上想要存储值并稍后调用它,那么您需要对存储进行模板化。
如果您调用的方法只是特定单一类型的成员(即总是 xGPIO
),那么您甚至不需要模板。
另请注意,如果您存储要稍后调用的对象实例,则必须确保该对象的生命周期保持不变,直到您需要调用它(或者您需要制作一个副本,使用 std::shared_ptr
ETC。)。这也适用于使用 std::function
和对象指针或 std::ref
.