借由function类和bind函数实现多态

一、 std::function对象,std::function对象是对C++中现有的可调用实体的一种类型安全的包裹

#include < functional>

std::function< size_t(const char*)> print_func;

// normal function -> std::function object
size_t CPrint(const char*) { /*...*/ }
print_func = CPrint;
print_func("hello world"):

// functor -> std::function object
class CxxPrint
{
public:
    size_t operator()(const char*) { /*...*/ }
};
CxxPrint p;
print_func = p;
print_func("hello world");

在上面的例子中,我们把一个普通的函数和一个functor赋值给了一个std::function对象,然后我们通过该对象来调用。其它的C++中的可调用实体都可以像上面一样来使用。通过std::function的包裹,我们可以像传递普通的对象一样来传递可调用实体,这样就很好解决了类型安全的问题。了解了std::function的基本用法,下面我们来看一些使用过程中的注意事项:
(1)关于可调用实体转换为std::function对象需要遵守以下两条原则:

  • a. 转换后的std::function对象的参数能转换为可调用实体的参数
  • b.可高用实体的返回值能转换为std::function对象的(这里注意一下,所有的可调用实体的返回值都与返回void的std::function对象的返回值兼容)。

(2)std::function对象可以refer to满足(1)中条件的任意可调用实体
(3)std::function object最大的用处就是在实现函数回调,使用者需要注意,它不能被用来检查相等或者不相等

二、 bind是这样一种机制,它可以预先把指定可调用实体的某些参数绑定到已有的变量,产生一个新的可调用实体,这种机制在回调函数的使用过程中也颇为有用。

#include < functional>

int Func(int x, int y);
auto bf1 = std::bind(Func, 10, std::placeholders::_1);
bf1(20); ///< same as Func(10, 20)

class A
{
public:
    int Func(int x, int y);
};

A a;
auto bf2 = std::bind(&A::Func, a, std::placeholders::_1, std::placeholders::_2);
bf2(10, 20); ///< same as a.Func(10, 20)

std::function< int(int)> bf3 = std::bind(&A::Func, a, std::placeholders::_1, 100);
bf3(10); ///< same as a.Func(10, 100)

上面的例子中,bf1是把一个两个参数普通函数的第一个参数绑定为10,生成了一个新的一个参数的可调用实体体; bf2是把一个类成员函数绑定了类对象,生成了一个像普通函数一样的新的可调用实体; bf3是把类成员函数绑定了类对象和第二个参数,生成了一个新的std::function对象。看懂了上面的例子,下面我们来说说使用bind需要注意的一些事项:
(1)bind预先绑定的参数需要传具体的变量或值进去,对于预先绑定的参数,是pass-by-value的
(2)对于不事先绑定的参数,需要传std::placeholders进去,从_1开始,依次递增。placeholder是pass-by-reference的
(3)bind的返回值是可调用实体,可以直接赋给std::function对象
(4)对于绑定的指针、引用类型的参数,使用者需要保证在可调用实体调用之前,这些参数是可用的
(5)类的this可以通过对象或者指针来绑定

三、 由function类和bind函数实现多态:

class CFather 
{
public:
    virtual ~CFather() {};
    virtual void saySomething() 
    {
        std::cout << "I am Father!" << std::endl;
    }
};

class CSon : public CFather 
{
public:
    virtual ~CSon() {};
    virtual void saySomething() override 
    {
        std::cout << "I am Son" << std::endl;
    }
};

class CDaughter : public CFather 
{
public:
    virtual ~CDaughter() {};
    virtual void saySomething() override 
    {
        std::cout << "I am Daughter" << std::endl;
    }
};

void functionBind() 
{
    std::cout << "I am functionBind" << std::endl;
};

void main() 
{
    std::function<void()> function;

    /*
      CFather*   father;
    */
    CSon*      son      = new CSon;
    CDaughter* daughter = new CDaughter;

    //取代传统的多态实现方式
    /*
      father = son;
      father->saySomething();
    */
    function = std::bind(&CSon::saySomething, son);
    function();

    //取代传统的多态实现方式
    /*
      father = daughter;
      father->saySomething();
    */
    function = std::bind(&CDaughter::saySomething, daughter);
    function();

    delete son;
    delete daughter;
}

猜你喜欢

转载自blog.csdn.net/qq_38216239/article/details/81357396