2012-10-30 125 views
4

摘要

我有一个存储优化问题并运行求解器的类。 如果求解器失败,我想考虑一个子问题并使用相同的求解器(和类)来求解。指向函数成员和非成员的指针

引言

优化问题本质上是很多(数学)函数。问题函数定义在类外,但子问题的功能都定义在类内部,所以他们有不同的类型(例如void (*)void (MyClass::*)

起初,我以为我可以投的成员函数的非-member指针到函数的类型,但我发现我不能那么我在寻找一些其他的方式

示例代码

的示例代码来模拟我的问题:。

#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::functionstd::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(); 
} 

PS。创建std::function有超过10个变量似乎可能(编译,但是我没有测试)与

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

但对于超过10个参数创建std::bind似乎并不那么容易。

+0

+1奈斯利提出的问题。 –

+0

@ThomasMatthews谢谢。 :) –

回答

3

std::functionstd::bind,和lambda表达式是你在找什么。总之,函数指针是非常糟糕的事情,应该在火中烧掉。在长,std::function可以存储与正确的签名被调用任意函数对象,并且可以使用std::bind或lambda来生成一个函数对象是快速,方便地调用你的成员函数。

编辑:那么你将不得不推出自己的std::function相当于支持超过10个参数。

+0

我忘了提。我尝试改变为std :: function,但我原来的函数有10多个参数(这是一个Fortran子例程)。 –

+1

为什么要把函数指针烧在地狱里? –

+0

@AbelSiqueira:获得更好的编译器(或添加标志'-std = C++ 11'):C++ 2011支持可变参数,并且可以传入任意数量的参数。如果这不适用于你,只需输入适当数量参数的'std :: function​​'版本。 –