鱼C论坛

 找回密码
 立即注册
查看: 3248|回复: 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 支持楼主!

查看全部评分

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

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

1.bind方式(不推荐)
#include <iostream>
#include <boost\asio.hpp>
#include <boost\bind.hpp>
#include <boost\date_time\posix_time\posix_time.hpp>

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() {
                // ...d0 something ...
                std::cout << "in print ..." << std::endl;
        }

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

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

        printer p(io);

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

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

如果是用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以上版本才能编译
#include <iostream>
#include <boost\asio.hpp>
#include <boost\date_time\posix_time\posix_time.hpp>

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

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

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

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

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

        printer p(io);

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

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


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();
 }
});
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-1-19 17:07

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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