将指针传递给类方法作为函数参数

时间:2013-12-23 14:04:23

标签: c++ class pointers

我有一个班级

class A{
    A(/*constructor arguments*/);
    double MethA(double);
};

我想在一个带有指向函数的指针的函数中传递方法MethA

double function(double (*f)(double), double x){
    return f(x);
}

所以我正在做的是打电话

A a(/*constructor arguments*/);
function(a.MethA,1.0);

但它没有编译。

我很确定这个问题在其他地方得到了解答,但我无法找到,因为我不确定我使用的术语是否正确。我是否尝试将类方法上的指针作为函数参数传递?或者,将函数指针作为类的成员传递...我很困惑: - (

3 个答案:

答案 0 :(得分:2)

当你需要使用指向成员函数的指针时,你需要传递两个不同的东西:

  • 要调用的成员函数和
  • 调用它的实例。

在C ++中,您不能将它们组合在一个结构中,就像您想要的那样:

A a;
bar(a.foo);

无效C ++。

相反,你必须这样做:

A a;
bar(a, &A::foo)

并相应地声明并实现bar():

void bar(A &a, void (A::*method)()) {
    a.*method();
}

答案 1 :(得分:1)

如果您想了解如何正确使用成员函数指针,请参阅Arkadiy's答案。

<强> BUT

根据评论中的要求:如果您使用的编译器支持lambdas(有些没有完整的C ++ 11)。您可以执行以下操作,它看起来更像您尝试使用的语法。

您对function的定义更改为:

template <typename F>
double function(F f, double x){
    return f(x);
};

一个函数模板,它接受一个可用double调用的参数。

在您的通话现场,您可以这样做:

A a(/*constructor arguments*/);
function([&](double x){return a.MethA(x);},1.0);

通过引用生成一个就地绑定到类实例a的函数对象。

模板可以在<type_traits>中使用一些魔法制作完全类型安全,但是如果你传递了一些非常错误的话,它会给你模板喷射。

答案 2 :(得分:0)

它必须是静态函数!

#include <iostream>
#include <cassert>
class A {
public:
  static double MethA(double x) { return 5 * x; }
};
typedef double (*ftype)(double);
double function(ftype f) {
  assert(f != NULL);
  return f(7);
}
int main(int, char**) {
  // expect "35\n" on stdout
  std::cout << function(A::MethA) << "\n";
}

它必须是静态的,因为在不知道你引用的是哪个A对象的情况下,你无法访问任何A的变量!如果需要A的非静态成员变量,则需要将对a的引用传递给静态函数:

#include <iostream>
#include <cassert>
class A {
  double fX;
public:
  A(double x) : fX(x) { }
  double methB(double x) const { return fX * x; }
  static double MethB(double x, const A& a) {
    return a.methB(x);
  }
};
typedef double (*ftype2)(double, const A&);
double function_with_context(ftype2 f, const A& a) {
  assert(f != NULL);
  return f(7, a);
}

int main(int, char**) {
  A a(6);
  // expect "42\n" on stdout
  std::cout << function_with_context(A::MethB, a) << "\n";
}

但有时候使用继承和多态来实现这种接口会更好:

#include <iostream>
class MyInterface {
public:
  virtual double f(double x) const = 0;
};

class A : public MyInterface {
  double fX;
public:
  A(double x) : fX(x) { }
  double f(double x) const {
    return fX * x;
  }
};

double function(const MyInterface& o) {
  return o.f(7);
}

int main(int, char**) {
  A a(6);
  // expect "42\n" on stdout
  std::cout << function(a) << "\n";
}