4

関数ポインタに問題があります。typedef double (*function)(double *x) const;を介して関数ポインターを定義する基本クラスがあります。

  • 簡単な補足質問: 上記の typedef がコンパイルされないのはなぜですか?

    次のエラーが表示されます:エラー: 'function' の 'const' および 'volatile' 関数指定子が型宣言で無効です

以下の部分では、typedef double (*function)(double *x)を使用します。現在、各ドーター クラスは、このタイプの関数の複数の異なるバージョンを実装できます。列挙型を介して、選択した関数を選択します。これにより、非メンバー関数ポインター (基本クラスで定義されている) が、娘クラスのこれらのメンバー関数ポインターのいずれかによって初期化されるように設定されます。コード スニペットを次に示します。

ドーター クラスのソース ファイル:

PndLmdROOTDataModel1D::PndLmdROOTDataModel1D(interpolation_type intpol_type) {
  if(intpol_type == CONSTANT) {
    setModelFunction(&PndLmdROOTDataModel1D::evaluateConstant); 
  }
  else if (intpol_type == SPLINE) {
    setModelFunction(&PndLmdROOTDataModel1D::evaluateSpline);
  }
  else {
    setModelFunction(&PndLmdROOTDataModel1D::evaluateLinear);
  }
}

基本クラス (ヘッダー ファイル):

class MultiModel1D: public Model1D {
protected:
  function model_func;

public:
  MultiModel1D();
  virtual ~MultiModel1D();

  void setModelFunction(function f);
}

コンパイルすると、次のエラーが発生します。

注: 'double (PndLmdROOTDataModel1D::*)(double*)' から 'function {aka double (*)(double*)}' への引数 1 の既知の変換はありません</p>

速度の問題のため、関数ポインターを使用しています (少なくとも、これは、いくつかのスイッチケースを常に実行するよりも高速であると思います)。私は何を間違っていますか?たぶん、より良い代替手段として役立ついくつかのデザインパターンもあります...よろしくお願いします!

スティーブ

4

2 に答える 2

15

これは、(フリー)関数ポインターとメンバー関数ポインターの間に根本的な違いがあるためです。あなたの「サイド質問」には、すでに問題のヒントが含まれています。説明すると、次のいずれかを実行できます。

typedef double (SomeClass::*function)(double *x) const;

また

typedef double (*function)(double *x);

ただし、非メンバー関数をconst関数レベルで宣言することはできません。これらの型は相互に変換できません。これは、コンパイラが指摘しているコードの問題です。

それらを変換できた場合、問題が発生します。メンバー関数ポインターは、メンバー関数が呼び出されたときにオブジェクトが呼び出される必要があることをコンパイラーに通知しますthis。ポインターを通常の関数ポインターにキャストできる場合、このオブジェクトは欠落し、結果としてすべてのパラメーターが混乱する可能性があります。だから、いや、あなたは本当にそれらをキャストすることはできません。現実はさらに複雑です(複数/仮想継承)が、全体像を把握できます...

于 2013-03-19T17:15:12.843 に答える
8

私たちが書かないのと同じ理由で:

void foo() const
{
   // ...
}

クラス宣言の外。非メンバー関数はできませんconst

関数ポインターは通常の関数ポインターであり、メンバー関数へのポインターではないため、constそこでは意味がありません。

于 2013-03-19T17:15:17.853 に答える