鱼C论坛

 找回密码
 立即注册
查看: 3411|回复: 1

[技术交流] 《C++Boost库asio》第三篇 怎么绑定成员函数(之前绑定的是自由函数):

[复制链接]
发表于 2017-7-9 11:56:08 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x

怎么绑定成员函数(之前绑定的是自由函数):
1.bind方式(不推荐) 2. lambda(推荐)
async_wait(boost::bind(&printer::print, this));
bind参数:1。成员函数的地址形式 2。调用者

class printer {
public:
  printer(boost::asio::io_service &io) : timer_(io, boost::posix_time::seconds(1)),

count_(0) {
   timer_.async_wait(boost::bind(&printer::print, this));
  }
  ~printer() { std::cout << "Final count is " << count_ << std::endl; }

  void print() {
    // ....do something ....
  }

private:
  boost::asio::deadline_timer timer_;
  int count_;
};

int main() {
boost::asio::io_service io;
printer p(io);
io.run();
return 0;
}

如果是用STL的bind来绑定
#include <functional>//跟函数相关的都在这里头
把bind 改成 std::bind

如果是用lambda来绑定
不用引入头文件
改成 timer_.async_wait([this](const auto&){this->print();});
const auto&是函数自带的参数,boost::system::error_code,是一个错误码,用auto来替代的这种

方式,要求C++14以上版本才能编译

bind返回的是 function<void(const boost::system::error_code)>
lambda返回的是lambda
区别:
function是真正生成一个类的实体,有默认的回调,默认的赋值,操作等。。而且不能在编译器展

开,sizeof也相对要大
lambda可以在编译器展开,开销很小,效率高

避免:绑定的资源,在回调之前就已经失效了
比如这里的this,[]里的资源,timer_.async_wait([this]{const auto&){this->print();});不能让

它在回调之前失效,比如让资源不失效?或者让正常析构的时候,把回调取消掉?先试试,在析构的

时候,调用timer_.cancel() 取消等待的回调,会出现的问题是:timer_在自身析构的过程中,也会

调用cancel的过程,而且如果回调函数中的参数有我自身,实际上已经没有任何意义了,在析构的时

候调用已经晚了,所以cancel没有用
不太正确但是安全的方式:
进行一次判断
timer_async_wait([this](const auto& error) {
if(error == boost::asio::error::operation_aborted) {
  std::cout << "cancel now\n";//出现问题,这个地方不能调用this等资源
} else {
  this -> print();
}
});


评分

参与人数 1鱼币 +5 收起 理由
小甲鱼 + 5 支持楼主!

查看全部评分

本帖被以下淘专辑推荐:

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2017-7-10 11:28:43 | 显示全部楼层
怎么绑定成员函数(之前绑定的是自由函数):

1.bind方式(不推荐)

  1. #include <iostream>
  2. #include <boost\asio.hpp>
  3. #include <boost\bind.hpp>
  4. #include <boost\date_time\posix_time\posix_time.hpp>

  5. class printer {
  6. public:
  7.         printer(boost::asio::io_service &io) :
  8.                 timer_(io, boost::posix_time::seconds(1)),
  9.                 count_(0)
  10.         {
  11.                 timer_.async_wait(boost::bind(&printer::print, this));
  12.         }

  13.         ~printer() {
  14.                 std::cout << "Final count is " << count_ << std::endl;
  15.         }

  16.         void print() {
  17.                 // ...d0 something ...
  18.                 std::cout << "in print ..." << std::endl;
  19.         }

  20. private:
  21.         boost::asio::deadline_timer timer_;
  22.         int count_;
  23. };

  24. int main()
  25. {
  26.         // 我们的程序和操作系统底层之间的一个相互传递的枢纽
  27.         // 会把事件按照一定方式进行处理;
  28.         boost::asio::io_service io;

  29.         printer p(io);

  30.         // 开始运行;
  31.         io.run();

  32.         std::cout << "mian finish run \n" << std::endl;// 提示下main函数已经结束了
  33.         system("pause");// 让VS控制台程序不会一闪而过;
  34.     return 0;
  35. }
复制代码


如果是用STL的bind来绑定
#include <functional>//跟函数相关的都在这里头
把bind 改成 std::bind

2. lambda(推荐)

如果是用lambda来绑定
不用引入头文件
改成 timer_.async_wait([this](const auto&){this->print();});
const auto&是函数自带的参数,boost::system::error_code,是一个错误码,用auto来替代的这种方式,要求C++14以上版本才能编译

  1. #include <iostream>
  2. #include <boost\asio.hpp>
  3. #include <boost\date_time\posix_time\posix_time.hpp>

  4. class printer {
  5. public:
  6.         printer(boost::asio::io_service &io) :
  7.                 timer_(io, boost::posix_time::seconds(1)),
  8.                 count_(0)
  9.         {
  10.                 timer_.async_wait([this](const boost::system::error_code&) {this->print();});
  11.         }

  12.         ~printer() {
  13.                 std::cout << "Final count is " << count_ << std::endl;
  14.         }

  15.         void print() {
  16.                 // ...d0 something ...
  17.                 std::cout << "in print ..." << std::endl;
  18.         }

  19. private:
  20.         boost::asio::deadline_timer timer_;
  21.         int count_;
  22. };

  23. int main()
  24. {
  25.         // 我们的程序和操作系统底层之间的一个相互传递的枢纽
  26.         // 会把事件按照一定方式进行处理;
  27.         boost::asio::io_service io;

  28.         printer p(io);

  29.         // 开始运行;
  30.         io.run();

  31.         std::cout << "mian finish run \n" << std::endl;// 提示下main函数已经结束了
  32.         system("pause");// 让VS控制台程序不会一闪而过;
  33.     return 0;
  34. }
复制代码



bind返回的是 function<void(const boost::system::error_code)>
lambda返回的是lambda
区别:
function是真正生成一个类的实体,有默认的回调,默认的赋值,操作等。。而且不能在编译器展开,sizeof也相对要大
lambda可以在编译器展开,开销很小,效率高


避免:绑定的资源,在回调之前就已经失效了
比如这里的this,[]里的资源,timer_.async_wait([this]{const auto&){this->print();});不能让

它在回调之前失效,比如让资源不失效?或者让正常析构的时候,把回调取消掉?先试试,在析构的

时候,调用timer_.cancel() 取消等待的回调,会出现的问题是:timer_在自身析构的过程中,也会

调用cancel的过程,而且如果回调函数中的参数有我自身,实际上已经没有任何意义了,在析构的时候调用已经晚了,所以cancel没有用
不太正确但是安全的方式:
进行一次判断

  1. timer_async_wait([this](const auto& error) {
  2. if(error == boost::asio::error::operation_aborted) {
  3.   std::cout << "cancel now\n";//出现问题,这个地方不能调用this等资源
  4. } else {
  5.   this -> print();
  6. }
  7. });
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-21 02:15

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表