函数成员指针和非成员指针

4

摘要

我有一个类,用于存储优化问题并在该问题上运行求解器。如果求解器失败,我想考虑子问题,并使用相同的求解器(和类)进行求解。

介绍

优化问题本质上是许多(数学)函数。问题函数在类外定义,但子问题函数在类内定义,因此它们具有不同的类型(例如void (*)void (MyClass::*))。

起初,我认为可以将成员函数强制转换为非成员指向函数的指针类型,但我发现不能这样做。因此,我正在寻找其他方法。

示例代码

一个模拟我的问题的示例代码:

#include <iostream>

using namespace std;

typedef void (*ftype) (int, double);

// Suppose foo is from another file. Can't change the definition
void foo (int n, double x) {
  cout << "foo: " << n*x << endl;
}

class TheClass {
  private:
    double value;
    ftype m_function;
    void print (int n, double x) {
      m_function(size*n, value*x);
        }
  public:
    static int size;
    TheClass () : value(1.2), m_function(0) { size++; }
    void set_function (ftype p) { m_function = p; }
    void call_function() {
      if (m_function) m_function(size, value);
    }
    void call_ok_function() {
      TheClass ok_class;
      ok_class.set_function(foo);
      ok_class.call_function();
    }
    void call_nasty_function() {
      TheClass nasty_class;
//      nasty_class.set_function(print);
//      nasty_class.set_function(&TheClass::print);
      nasty_class.call_function();
    }
};
int TheClass::size = 0;

int main () {
  TheClass one_class;

  one_class.set_function(foo);
  one_class.call_function();
  one_class.call_ok_function();
  one_class.call_nasty_function();
}

正如示例所示,成员函数不能是静态的。另外,我不能重新定义原始问题函数以接收对象。
感谢任何帮助。
编辑
我忘了提到。我尝试改为std::function,但是我的原始函数有超过10个参数(它是一个Fortran子例程)。
解决方案
我按照建议更改为std :: function和std :: bind,但没有重新设计具有超过10个参数的函数。我决定创建一个中间函数。以下代码说明了我所做的事情,但使用较少的变量。感谢所有人。
#include <iostream>
#include <boost/tr1/functional.hpp>

using namespace std;

class TheClass;

typedef tr1::function<void(int *, double *, double *, double *)> ftype;

// Suppose foo is from another file. Can't change the definition
void foo (int n, int m, double *A, double *x, double *b) {
    // Performs matrix vector multiplication x = A*b, where
    // A is   m x n
}

void foo_wrapper (int DIM[], double *A, double *x, double *b) {
    foo(DIM[0], DIM[1], A, x, b);
}

class TheClass {
    private:
        ftype m_function;
        void my_function (int DIM[], double *A, double *x, double *b) {
            // Change something before performing MV mult.
            m_function(DIM, A, x, b);
        }
    public:
        void set_function (ftype p) { m_function = p; }
        void call_function() {
            int DIM[2] = {2,2};
            if (m_function) m_function(DIM, 0, 0, 0);
        }
        void call_nasty_function() {
            TheClass nasty_class;
            ftype f = tr1::bind(&TheClass::my_function, this, _1, _2, _3, _4);
            nasty_class.set_function(f);
            nasty_class.call_function();
        }
};

int main () {
    TheClass one_class;

    one_class.set_function(foo_wrapper);
    one_class.call_function();
    one_class.call_nasty_function();
}

备注:使用 std::function 带有超过10个变量似乎是可能的(已编译,但我没有测试)

#define BOOST_FUNCTION_NUM_ARGS 15
#include <boost/function/detail/maybe_include.hpp>
#undef BOOST_FUNCTION_NUM_ARGS

但是创建超过10个参数的std::bind似乎并不容易。

1个回答

3
"std::function"、"std::bind" 和 lambda 表达式是您需要寻找的内容。简而言之,函数指针是非常糟糕的东西,应当被消灭。具体来说,"std::function" 可以存储任何能够使用正确签名调用的函数对象,并且您可以使用 "std::bind" 或 lambda 表达式来生成一个快速轻松调用成员函数的函数对象。
注:如果需要支持超过 10 个参数,则需要自己实现类似于 "std::function" 的功能。

我忘了提到。我尝试改用std::function,但我的原始函数有超过10个参数(它是一个Fortran子程序)。 - Abel Siqueira
@AbelSiqueira:使用更好的编译器(或添加标志“-std=c++11”):C++ 2011支持可变参数,并且您可以传递任意数量的参数。如果这对您不起作用,只需键入具有适当数量参数的版本std::function<Signature>即可。 - Dietmar Kühl
@DietmarKühl:抱歉,找不到std::function<Signature>是什么或者如何工作的信息。你能指个方向或者给个例子吗?我不能使用-std=c++11,也不能更换编译器。 - Abel Siqueira
@DietmarKühl:我创建了一个带有13个参数的std::function<void(...)>。要定义一个处理13个参数的函数,头文件中只需要3行即可。但是我无法绑定这13个参数,并且找不到一种简单的方法来实现13个参数的绑定。 - Abel Siqueira
@DietmarKühl:最终我创建了一个带有8个参数的中间函数,第一个参数是一个包含多余部分的数组。在这个函数中,我调用了所需的函数。谢谢。 - Abel Siqueira
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接