如何将函数传递给函数?

时间:2010-06-11 22:37:12

标签: c++ qt refactoring

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

class CommandHandler
{
public:
  static void command_one(Item);
  static void command_two(Item);
};

我遇到DRY问题,我有2个函数,每个行都有完全相同的代码,但它调用的函数除外:

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
}

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

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);
}

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

9 个答案:

答案 0 :(得分: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);
}

答案 1 :(得分:5)

除了C方式(传递函数指针)或Jay here提到的C ++方式之外,还有其他(现代)c ++方式,带有boost或带有c +的编译器+ 0x支持:

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

这样可以封装一个仿函数,并且可以与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
}

答案 2 :(得分:4)

我发布了一个与此非常相似的问题,这就是我得到的解释:

Function Pointers

以下是我发布的问题的链接:Function callers (callbacks) in C?

答案 3 :(得分:2)

我可以想到两种方式。

  1. C风格方式:将要调用的函数作为函数指针传递。
  2. C ++方式:创建一个实现代码的基类,并用虚方法替换被调用的函数。然后从基类派生两个具体类,每个类以不同方式实现虚函数。

答案 4 :(得分:2)

如果您无法访问tr1或boost,另一种方法是使用函数模板。它非常简单,显然是一种C ++方式。

这是一个类似于你的可编辑示例:

#include <iostream>
using namespace std;

class CommandHandler
{
public:
   static void command_one(int i) { cout << "command_one " << i << endl; }
   static void command_two(int i) { cout << "command_two " << i << endl; }
};

template <typename Func>
void CommandCaller(Func f)
{
   f(1);
}

int main()
{
   CommandCaller(&CommandHandler::command_one);
   return 0;
}

答案 5 :(得分:1)

答案 6 :(得分:0)

静态成员函数可以简单地作为函数指针传递。

非静态可以作为成员函数指针+ this传递。

答案 7 :(得分:0)

void Refactored_CommandUser(static void (*func)(Item))
{
    // some code A

    func(item);

    // some code B
}

void CommandOne_User()
{
    Refactored_CommandUser(&CommandHandler::command_one);
}

void CommandTwo_User()
{
    Refactored_CommandUser(&CommandHandler::command_two);
}

答案 8 :(得分:0)

受到David Roriguez answer的启发,我自己试了一下,是的,它有效:

以下是将函数作为函数参数传递的“现代”方法的示例(愚蠢)代码:

#include <functional>    
#include <assert.h>

class Command
{
public:
  static int getSeven(int number_)
  {
    return 7 + number_;
  }
  static int getEight(int number_)
  {
    return 8 - number_;
  }
};

int func(std::tr1::function<int (int)> f, int const number_ )
{
  int const new_number = number_ * 2;
  int const mod_number = f(new_number);
  return    mod_number - 3;
}


int main()
{
  assert( func(Command::getSeven, 5)  ==  14 );
  assert( func(Command::getEight, 10) == -15 );

  return 0;
}

我在VS2008上尝试使用英特尔C ++编译器11.1并支持C ++ 0X(不知道是否真的需要C ++ 0x支持,因为它在TR1中)。

相关问题