一、 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;
}