2012-10-30 122 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​​'版本。 –