如何将函数作为参数传递

时间:2015-04-09 02:15:37

标签: c++ function-pointers

我有两种方法大致相同,所以我想重构它们。

一个简单的版本是:

void C::GetEmailAlerts(set<AlertPtr>& alertSet)
{
  ...
  ... 
  AlertPtr pAlert = Cache::Get()->GetAlert();
  for (...) {
    ...
    if (pAlert->isEmail())
      alertSet.insert(p);
  }
  ...
}

void C::GetMobileAlerts(set<AlertPtr>& alertSet)
{
  ...
  ... 
  AlertPtr pAlert = Cache::Get()->GetAlert();
  for (...) {
    ...
    if (pAlert->isMobile())
      alertSet.insert(p);
  }
  ...
}

是否有可能使它像:

void C::GetAlerts(set<AlertPtr>& alertSet, ??? func) // How to pass a function as parameter?
{
  ...
  ... 
  AlertPtr pAlert = Cache::Get()->GetAlert();
  for (...) {
    ...
    if (pAlert->func())
      alertSet.insert(p);
  }
  ...
}

所以我打电话:

C c;
c.GetAlerts(emailSet, isEmail);
c.GetAlerts(mobileSet, isMobile);

------------------------编辑---------------------- -

也许一个通用的例子更容易证明我想要的东西:

#include <iostream>
using namespace std;

struct A
{
    int foo() { cout<<"in foo()"<<endl; }
    int bar() { cout<<"in bar()"<<endl; }
};

A *instance = new A();

struct C
{
public:
  void test1()
  {
    instance->foo();
  }
  void test2()
  {
    instance->bar();
  }

//  void test(???) // How to pass member function as a pointer?
//  {
//    instance->f();
//  }
};

int main()
{
  C c;
  c.test1();
  c.test2();

//  c.test(&A::foo);
//  c.test(&A::bar);

  return 0;
}

在第二个示例中,我想使用c.test(&A::foo);替换c.test1(),也许c.test2,c.test3,...

有干净的方法吗?

5 个答案:

答案 0 :(得分:0)

嗯,取决于。如果您使用的是C ++ 11,则可以使用auto类型,然后执行参数。否则,您需要知道该函数是intvoidchar等,然后执行给定的参数。

答案 1 :(得分:0)

如果isEmail像这样:bool AlertPtr::isEmail(),您应该使用以下代码:

void C::GetAlerts(set<AlertPtr>& alertSet, bool (AlertPtr::*func)())
{
    ...
    ... 
    AlertPtr pAlert = Cache::Get()->GetAlert();
    for (...) {
        ...
        if (pAlert->func)
            alertSet.insert(p);
    }
    ...
}

答案 2 :(得分:0)

为什么不在同一个功能中级联if (pAlert->isMobile())if (pAlert->isEmail())

使用函数指针来处理这个问题似乎是过度工程的方式。

void C::GetAlerts(set<AlertPtr>& emailAlertSet, set<AlertPtr>& mobileAlertSet)
{
  ...
  ... 
  AlertPtr pAlert = Cache::Get()->GetAlert();
  for (...) {
    ...
    if (pAlert->isEmail()) {
      emailAlertSet.insert(p);
    else if (pAlert->isMobile()) {
      mobileAlertSet.insert(p);
    }

  }
  ...
}

答案 3 :(得分:0)

非常简单,只需使用命名空间在命名空间中定义每个命名空间,并且可以使用scoop运算符轻松访问它们

答案 4 :(得分:0)

对于可能感兴趣的人,我终于想出了如何做到这一点:

void C::GetAlerts(set<AlertPtr>& alertSet, bool (AlertClass::func)())
{
  ...
  if ((pAlert->*func)())
    ...
}

这就是我们称之为这个功能的方式:

C c;
c.GetAlerts(emailSet, &AlertClass::isEmail);
c.GetAlerts(mobileSet, &AlertClass::isMobile);

第二个例子的完整解决方案:

#include <functional>
#include <iostream>
using namespace std;

struct A
{
    int foo() { cout<<"in foo()"<<endl; }
    int bar() { cout<<"in bar()"<<endl; }
};

A *instance = new A();

struct C
{
public:
  void testFoo()
  {
    instance->foo();
  }
  void testBar()
  {
    instance->bar();
  }

  void test(int (A::*p)())
  {
    (instance->*p)();
  }
};

int main()
{
  C c;
  c.testFoo();
  c.testBar();

  c.test(&A::foo);
  c.test(&A::bar);

  return 0;
}