8

operator()クラスに設定されたオプションに基づいて、いくつかの異なる方法をクラスに実装したいと考えています。これは何度も呼び出されるため、分岐するものは使用したくありません。理想的にはoperator()、メソッドで設定できる関数ポインタです。ただし、これが実際にどのように見えるかはわかりません。私は試した:

#include <iostream>

class Test {
public:
  int (*operator())();

  int DoIt1() {
    return 1;
  }

  int DoIt2() {
    return 2;
  }

  void SetIt(int i) {
    if(i == 1) {
      operator() = &Test::DoIt1;
    } else {
      operator() = &Test::DoIt2;
    }
  }
};

int main()
{
  Test t1;

  t1.SetIt(1);

  std::cout << t1() << std::endl;

  t1.SetIt(2);

  std::cout << t1() << std::endl;

  return 0;
}

別の関数ポインターを作成し、operator()関数からそれを呼び出すと、それが機能することはわかっています。しかし、operator()関数自体を関数ポインタにすることは可能ですか? 私が投稿したものに沿ったもの(コンパイルされません)?

上記のコードは次のようになります。

test.cxx:5:21: エラー: 'operator()' を非関数として宣言

test.cxx: メンバー関数 'void Test::SetIt(int)':

test.cxx:17:16: エラー: 'operator()' が定義されていません

test.cxx:19:16: エラー: 'operator()' が定義されていません

test.cxx: 関数 'int main()' 内:

test.cxx:30:19: エラー: '(Test) ()' の呼び出しに一致しません</p>

test.cxx:34:19: エラー: '(Test) ()' の呼び出しに一致しません</p>

4

3 に答える 3

6

クラスは、使用する関数ポインタを何らかの方法で覚えておく必要があります。クラスメンバーとして保存します。

class Test
{ 
public:
    Test() : func(0) {}

    int operator()() {
        // Note that pointers to Test member functions need a pointer to Test to work.
        return (this->*func)(); // undefined behavior if func == 0
    }

    void SetIt(int i) { 
        if(i == 1) { 
            func = &Test::DoIt1; 
        } else { 
            func = &Test::DoIt2; 
        } 
    }

private:
    int DoIt1() { 
        return 1; 
    } 

    int DoIt2() { 
        return 2; 
    } 

    // Typedef of a pointer to a class method.
    typedef int (Test::*FuncPtr)(); 
    FuncPtr func; 
};

ただし、これを実行する前に、まずコードswitchをプロファイリングして、 orを介した分岐ifが実際にボトルネックになっているかどうかを確認してください (そうではない可能性があります)。最新のプロセッサーは直感に反する非常に優れたパフォーマンス特性を備えているため、コンパイラーはあなたが思っているよりも優れたコードを生成できる可能性があります。分岐が実際にコストがかかりすぎて使用できないことを確認する唯一の方法は、コードをプロファイリングすることです。(そして、「プロファイリング」とは、「テストせずに直感を思い付く」ではなく、「適切に設計された実験を実行する」ことを意味します。)

于 2012-04-20T04:36:14.467 に答える
1

C++03 と C++11 の両方で有効な 1 つのソリューションが @In silico によって提供されます。

C++11 のみの別のソリューションを次に示します。

std::function<int(Test*)>  func;

func = &Test::DoIt1; 

func(this); //this syntax is less cumbersome compared to C++03 solution

簡単なオンライン完全デモ

于 2012-04-20T04:46:19.933 に答える
1

operator()別のポインターを呼び出すインライン関数を作成できます。オプティマイザは余分な間接化を完全に取り除く必要があります。

于 2012-04-20T04:36:57.877 に答える