04-Timer.4-Using a member function as a completion handler
在本教程中,我们将学习如何将类成员函数用作完成处理程序。该程序的执行效果应与教程Timer.3中的示例程序完全相同。
#include <functional>
#include <iostream>
#include <asio.hpp>
#include <spdlog/spdlog.h>
// 不同于早期教程程序中那样将自由函数print定义为完成处理程序,我们现在定义了一个名为printer的类。
class Printer {
public:
// 该类的构造函数将接收一个对io_context对象的引用,并在初始化m_timer时使用它。
// 用于关闭程序的计数器现在也是该类的成员。
Printer(asio::io_context& _io, int _n = 1)
: m_timer(_io, std::chrono::seconds(1))
, m_count(0)
{
// std::bind函数不仅适用于自由函数,也同样适用于类成员函数。
// 由于所有非静态类成员函数都有一个隐式的this参数,我们需要将this绑定到函数上。如教程Timer.3所示,
// std::bind将我们的完成处理程序(现在是一个成员函数)转换为一个函数对象,
// 可以像具有void(const std::error_code&)签名的函数一样被调用。
//
// 您会注意到这里没有指定asio::placeholders::error占位符,
// 因为print成员函数不接受错误对象作为参数。
m_timer.async_wait(std::bind(&Printer::print, this, _n));
}
~Printer()
{
spdlog::info("Final count = {}", m_count);
}
// print成员函数与教程Timer.3中的print函数非常相似,
// 不同之处在于它现在操作的是类的数据成员,而不是将计时器和计数器作为参数传入。
void print(int _n)
{
if (m_count >= _n) {
return;
}
m_count++;
spdlog::info("Count = {}", m_count);
if (m_count < _n) {
m_timer.expires_at(m_timer.expiry() + asio::chrono::seconds(1));
m_timer.async_wait(std::bind(&Printer::print, this, _n));
}
}
private:
asio::steady_timer m_timer;
int m_count {};
};
// 主函数比之前简单多了,因为它现在在正常运行io_context之前声明了一个本地打印机对象。
int main()
{
spdlog::info("Starting...");
asio::io_context io;
Printer pointer(io, 10);
io.run();
return 0;
}