muduo库中的核心:std::bind和std::function

最近在读完陈硕大牛的《Linux多线程服务端编程》以及muduo源码后,对其中的一些实现细节有着十分深刻的印象,尤其是使用std::bind和std::function的回调技术。可以说,这两个大杀器简直就是现代C++的“任督二脉”,甚至可以解决继承时的虚函数指代不清的问题。在此详细叙述使用std::bind和std::function在C++对象之间的用法,用以配合解决事件驱动的编程模型。笔者才疏学浅,如果解释的不正确希望朋友们不吝赐教。

下面的所有讨论基于对象。

std::bind和std::function的基础用法

#include<iostream>
#include<functional>

typedef std::function<void()> Functor;

class Blas
{
    public:
        void add(int a,int b)
        {
            std::cout << a+b << std::endl;
        }

        static void addStatic(int a,int b)
        {
            std::cout << a+b << std::endl;
        }
};

int main(int argc,char** argv)
{
    Blas blas;

//使用bind绑定类静态成员函数
    Functor functor(std::bind(&Blas::addStatic,1,2));

//使用bind绑定类的chengyuan函数
    Functor functor(std::bind(&Blas::add,blas,1,2));

    functor();
    return 0;
}

上述代码中的区别是:如果不是类的静态成员函数,需要在参数绑定时,往绑定的参数列表中加入使用的对象。

使用std::function和std::bind实现回调功能

#include<iostream>
#include<functional>

typedef std::function<void()> Functor;

class Blas
{
    public:
        void setCallBack(const Functor& cb)
        {functor = cb;};

        void printFunctor()
        {functor();};

    private:
        Functor functor;
};

class Atlas
{
    public:
        Atlas(int x_) : x(x_)
        {
            //使用当前类的静态成员函数
            blas.setCallBack(std::bind(&addStatic,x,2));

            //使用当前类的非静态成员函数
            blas.setCallBack(std::bind(&Atlas::add,this,x,2));
        }

        void print()
        {
            blas.printFunctor();
        }

    private:
        void add(int a,int b)
        {
            std::cout << a+b << std::endl;
        }

        static void addStatic(int a,int b)
        {
            std::cout << a+b << std::endl;
        }
        Blas blas;
        int x;
};

int main(int argc,char** argv)
{
    Atlas atlas(5);
    atlas.print();
    return 0;
}

在以上代码中的

void add();
void addStatic();

两个函数在Atlas类中,并且可以自由操作Atlas的数据成员。尽管是将add()系列的函数封装成函数对象传入Blas中,并且在Blas类中调用,但是它们仍然具有操作Atlas数据成员的功能,在两个类之间形成了弱的耦合作用。但是如果要在两个类之间形成弱的耦合作用,必须在使用std::bind()封装时,向其中传入this指针:

std::bind(&Atlas::add,this,1,2);

也就是说,要在两个类之间形成耦合作用,要使用非静态的成员函数(私有和公有都可以)。代码如下:

#include<iostream>
#include<functional>

typedef std::function<void()> Functor;

class Blas
{
    public:
        void setCallBack(const Functor& cb)
        {functor = cb;};

        void printFunctor()
        {functor();};

    private:
        Functor functor;
};

class Atlas
{
    public:
        Atlas(int x_,int y_) : x(x_),y(y_)
        {
            //使用当前类的非静态成员函数
            blas.setCallBack(std::bind(&Atlas::add,this,x,2));
        }

        void print()
        {
            blas.printFunctor();
        }

    private:

        void add(int a,int b)
        {
            std::cout << y << std::endl;
            std::cout << a+b << std::endl;
        }
        Blas blas;
        int x,y;
};

int main(int argc,char** argv)
{
    Atlas atlas(5,10);
    atlas.print();
    return 0;
}

这样,便可以Atlas便可以在Blas类中注册一些函数对象,这些函数对象在处理Blas数据的同时(在std::bind中预留位置传入Blas的参数),还可以回带处理Atlas的数据,形成回调作用。代码如下:

#include<iostream>
#include<functional>

typedef std::function<void(int,int)> Functor;

class Blas
{
    public:
        void setCallBack(const Functor& cb)
        {functor = cb;};

        void printFunctor()
        {functor(x,y);};

    private:
        int x = 10;
        int y = 10;
        Functor functor;
};

class Atlas
{
    public:
        Atlas(int x_,int y_) : x(x_),y(y_)
        {
            //使用当前类的非静态成员函数
            blas.setCallBack(std::bind(&Atlas::add,this,std::placeholders::_1,std::placeholders::_2));
        }

        void print()
        {
            blas.printFunctor();
        }

        void printFunctor()
        {functor(x,y);};

    private:
        int x = 10;
        int y = 1:;
        Functor functor;
};

class Atlas
{
    public:
        Atlas(int x_,int y_) : x(x_),y(y_)
        {
            //使用当前类的非静态成员函数
            blas.setCallBack(std::bind(&Atlas::add,this,std::placeholders::_1,std::placeholders::_2));
        }

        void print()
        {
            blas.printFunctor();
        }

    private:

        void add(int a,int b)
        {
            std::cout << y << std::endl;
            std::cout << a+b << std::endl;
        }
        Blas blas;
        int x,y;
};

int main(int argc,char** argv)
{
    Atlas atlas(5,10);
    atlas.print();
    return 0;
}

原文地址:https://www.cnblogs.com/ukernel/p/9191109.html

时间: 2024-11-07 00:01:04

muduo库中的核心:std::bind和std::function的相关文章

浅析muduo库中的线程设施

muduo是目前我在学习过程中遇到的最具有学习意义的网络库,下文将分析muduo库中的基础设施--Thread和ThreadPool. 首先,介绍在多线程编程中不可缺少的同步措施--Mutex和Condition. Mutex ``` /Mutex.h/ class MutexLock : boost::noncopyable { public: MutexLock() : holder_(0) { MCHECK(pthread_mutex_init(&mutex_, NULL));//MCHE

c++11特性与cocos2d-x 3.0之std::bind与std::function

昨天同事让帮忙写一小功能,才发现cocos2d-x 3.0 和 cocos2d-x 3.0rc0 差别还是相当大的. 发现Label这一个控件,3.0就比rc0版本多了一个创建函数,更为关键的是3.0内的Label锚点是在ccp(0.5,0.5),而一直3.0rc0是ccp(0,0). 累觉不爱.尽管cocos2d-x改变太快,兼容性一次次的暴露出不足,但是,总归是向好的方向进行.于是下载了3.0来玩玩~ cocos new 出新的项目之后,仔细阅读代码,才发现了一句3.0区别于2.0的代码:

std::bind和std::function

std::bind 用于绑定一个函数,返回另外一种调用方式的函数对象 ,可以改变参数顺序 和个数 std::function 用于构建一个函数特别是 回调函数  ,用于替代 函数指针/*常和匿名函数一起用回调*/ 参考以下代码 #include<iostream> #include "functional" using namespace std; double calculate(double x, double y, char op) { switch (op) { c

muduo库中TcpServer一次完整的工作流程

模拟单线程情况下muduo库的工作情况 muduo的源代码对于一个初学者来说还是有一些复杂的,其中有很多的回调函数以及交叉的组件,下面我将追踪一次TCP连接过程中发生的事情,不会出现用户态的源码,都是库内部的运行机制.下文笔者将描述一次连接发生的过程,将Channel到加入到loop循环为止. 监听套接字加入loop循环的完整过程 首先创建一个TcpServer对象,在的创建过程中,首先new出来自己的核心组件(Acceptor,loop,connectionMap,threadPool)之后T

浅析muduo库中的定时器设施

一个设计良好的定时器在服务端的应用程序上至关重要,muduo定时器的实现陈硕大牛在书中已经详细的谈过,笔者尝试从源码的角度解读定时器的实现,如果理解不对,欢迎指正. 在muduo的定时器系统中,一共由四个类:Timestamp,Timer,TimeId,TimerQueue组成.其中最关键的是Timer和TimerQueue两个类.此文只解释初读时让人非常迷惑的TimerQueue类,这个类是整个定时器设施的核心,其他三个类简介其作用. 其中Timestamp是一个以int64_t表示的微秒级绝

STL C++ std::bind操作例子,仿函数操作配合算法库操作

1.stl::bind 和std::mem_fun_ref系列的配合使用出现了问题,多参形式不知道如何组织.适配器的操作真心难受!!!只能迷迷糊糊地用着.要使用非质变算法时需要作用于容器时只能考虑lambda或者transfer操作.待续 // functor-adapter_p431.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <algorithm>//元素操作算法 #include <functiona

C++ 11 std::function std::bind使用

cocos new 出新的项目之后,仔细阅读代码,才发现了一句3.0区别于2.0的代码: auto closeItem = MenuItemImage::create( "CloseNormal.png", "CloseSelected.png", CC_CALLBACK_1(HelloWorld::menuCloseCallback, this)); 2.0内的代码用的不是CC_CALLBACK_1而是menu_selector. CC_CALLBACK系列是3.

std::bind接口与实现

前言 最近想起半年前鸽下来的Haskell,重温了一下忘得精光的语法,读了几个示例程序,挺带感的,于是函数式编程的草就种得更深了.又去Google了一下C++与FP,找到了一份近乎完美的讲义,然后被带到C++20的ranges library,对即将发布的C++20满怀憧憬.此时,我猛然间意识到,看别人做,觉得自己也能做好,在游戏界叫云玩家,在编程界就叫云程序员啊! 不行,得找点事干.想起同样被我鸽了很久的<functional>系列,刚好与函数式编程搭点边,就动笔写吧!这就是本文的来历. 找

实战c++中的vector系列--对vector&amp;lt;自己定义类&amp;gt;使用std::find 和 std::find_if 算法

之前博客讲了一些关于std::find和std::find_ if的一些使用方法.可是没有讲述对于vector中存储的是自己定义的类.那么怎么样使用std::find和std::find_if进行查找呢? 先定义一个类: class Item { private: std::string m_ItemId; int m_Price; int m_Count; public: Item(std::string id, int price, int count): m_ItemId(id), m_C