如何将函数传递给函数?

siv*_*udh 4 c++ refactoring qt

假设我有一个包含2个静态函数的类:

class CommandHandler
{
public:
  static void command_one(Item);
  static void command_two(Item);
};
Run Code Online (Sandbox Code Playgroud)

我有一个DRY问题,我有两个函数,每个行都有完全相同的代码,除了它调用的函数:

void CommandOne_User()
{
  // some code A

  CommandHandler::command_one(item);

  // some code B
}

void CommandTwo_User()
{
  // some code A

  CommandHandler::command_two(item);

  // some code B
}
Run Code Online (Sandbox Code Playgroud)

我想删除重复,理想情况下,执行以下操作:

void CommandOne_User()
{
  Function func = CommandHandler::command_one();

  Refactored_CommandUser(func);
}

void CommandTwo_User()
{
 Function func = CommandHandler::command_one();

 Refactored_CommandUser(func);
}

void Refactored_CommandUser(Function func)
{
  // some code A

  func(item);
}
Run Code Online (Sandbox Code Playgroud)

我可以访问Qt,但不能访问Boost.有人可以帮我建议如何重构这样的东西吗?

sth*_*sth 6

你可以使用函数指针:

// type of the functions
typedef void Function(Item);

void CommandOne_User() {
  // function pointer
  Function *func = CommandHandler::command_one;
  Refactored_CommandUser(func);
}

void CommandTwo_User() {
  // can also be used directly, without a intermediate variable
  Refactored_CommandUser(CommandHandler::command_two);
}

// taking a function pointer for the command that should be executed
void Refactored_CommandUser(Function *func) {
  // calling the funcion (no explicit dereferencing needed, this conversion is
  // done automatically)
  func(item);
}
Run Code Online (Sandbox Code Playgroud)


Dav*_*eas 5

除了Ç方式(通过一个函数指针)或周杰伦提到的C++的方式在这里还有就是其他的(现代)C++与升压或用的C++ 0x的支持编译器的方式:

void Refactored_CommandUser( boost::function<void (Item)> f ) {
   // alternatively std::function with proper compiler support
}
Run Code Online (Sandbox Code Playgroud)

它的优点是封装了一个仿函数,并且可以与boost::bind(或std::bind)结合使用,不仅可以传递与签名完全匹配的自由函数指针,还可以传递其他内容,例如带有对象的成员指针:

struct test {
   void f( Item );
};
void foo( Item i, std::string const & caller );
void bar( Item i ); 
int main() {
   test t;
   Refactored_CommandUser( boost::bind( &test::f, &t, _1 ) );
   Refactored_CommandUser( boost::bind( foo, _1, "main" ) );
   Refactored_CommandUser( bar ); // of course you can pass a function that matches directly
}
Run Code Online (Sandbox Code Playgroud)