[modern c++] 函数对象/可调用对象 式编程的优点

前言:

modern c++ 的一个重要特性就是 函数对象/可调用对象 式编程,代表性的用法为 boost::bind,std::bind,lambda 。这些组件的功能是把一段代码封装程一个可以可调用对象,这个对象可以存在于堆中,也可以存在于栈中,本质上是创建一个临时类,再把传递给可调用对象的局部变量作为类的成员变量存储起来,这里的存储可以是值存储,也可以是引用或者地址,因此需要考虑生命周期的问题。当把可调用对象作为对象来使用,比如入参,全局变量,静态全局变量等等。可以让其存在于堆或者栈里。

需要注意的是,如果成员变量(std::bind构造时非placehold入参,lambda的捕获列表)都是 CopyConstructible 的,那么 std::bind 和 lambda 都是 CopyConstructible  的。这其实也就是再说可调用对象底层的临时类是 CopyConstructible 的。

优点:

函数对象/可调用对象 式编程看起来很复杂,而且有时候会让人觉得是否有必要这样使用,简单的函数调用不是也可以实现函数调用么,为什么要封装一下呢?其实这种编程方式的优点还是很明显的,特别是在处理那些需要层层初始化的业务逻辑中。

//CompA.cpp
int paramA = 1;
bool ret = init_CompA(paramA);
if(!ret){
  return;
}

//CompB.cpp
int paramB = 1;
bool ret = init_CompB(paramB);
if(!ret){
  uninit_CompA(); //error , need unint component previously inited
  return;
}

//CompC.cpp
int paramC = 1;
bool ret = init_CompC(paramC);
if(!ret){
  uninit_CompA(); //error , need unint component previously inited
  uninit_CompB(); //error , need unint component previously inited
  return;
}

//main.cpp
//依次进入Comp A/B/C ,需要在A/B/C中来回跳,同时需要判断各个组件的执行情况,这种
//代码逻辑不集中,特别是针对于 init 这种必须要做的行为时,有很大的风险导致资源释放
//有残留。

===============================

//1.准备初始化任务
std::function<bool(int)> fA= std::bind(init_CompA);
std::function<bool(int)> fB= std::bind(init_CompB);
std::function<bool(int)> fC= std::bind(init_CompC);
std::vector<std::function<bool(int)>> v_initlist;
v_initlist.push_back(fA);
v_initlist.push_back(fB);
v_initlist.push_back(fC);

....

//2.集中init,且可以互相得知各个组件的初始化情况。
bool initAll(std::vector<std::function<bool(int)>> v){
  for(auto f : v){
    f();
  }
}
//根据 f() 的结果集中回滚

简言之,把本应该或适合集中做的任务集中到一起,避免因为代码划分导致的逻辑分离。

猜你喜欢

转载自blog.csdn.net/ykun089/article/details/134500289