33

メンバー関数シグネチャの型定義を宣言したい。グローバル関数の typedef は次のようになります。

typedef int (function_signature)(int, int);
typedef int (*function_pointer) (int, int);

しかし、メンバー関数については同じことができません:

typedef int (foo::memberf_signature)(int, int);   // memberf_pointer is not a member of foo
typedef int (foo::*memberf_pointer)(int, int);

foo::クラスのメンバーにアクセスするための構文であるため、私には論理的に聞こえますfoo

署名だけを型定義するにはどうすればよいですか?

4

5 に答える 5

27

厄介な関数ポインターの構文に関する質問については、私は個人的にチート シートを使用します:関数ポインターのチュートリアル(ここからダウンロードできます。指摘してくれたVectorに感謝します)。

ただし、経験したように、メンバー関数のシグネチャは、通常の関数のシグネチャとは少し異なります。

ご存じのとおり、メンバー関数には隠しパラメーター がありthis、その型を指定する必要があります。

// C++11 and above.
using Member = int (Foo::*)(int, int);

// C++03 and below.
typedef int (Foo::*Member)(int, int);

関数に渡される最初の要素が a になることを指定できますFoo*(したがって、メソッドは、考えてみると、2 つだけでなく、実際には 3 つの引数を取ります。

ただし、タイプの指定を強制する別の理由もあります。

関数ポインターは仮想関数を参照する場合があり、その場合は非常に複雑になる可能性があります。したがって、メモリ内表現のサイズ自体は、関数の種類によって異なります。実際、Visual Studio では、関数ポインターのサイズは、通常のポインターのサイズの 1 倍から 4 倍の間で変動する場合があります。これは、特に関数が仮想であるかどうかによって異なります。

したがって、関数が参照するクラスは署名の一部であり、回避策はありません。

于 2011-01-29T08:36:47.107 に答える
8

テンプレート エイリアスの「型定義」の性質を利用することで、最新の C++ (post 11) でターゲット クラスを除外できます。必要なものは次のようになります。

template<typename T>
using memberf_pointer = int (T::*)(int, int); 

ただし、宣言の時点で、この構文を使用するメンバー関数へのポインターは、ターゲット クラスを指定する必要があります。

// D is a member function taking (int, int) and returning int
memberf_pointer<foo> mp = &foo::D; 
于 2015-07-27T09:36:35.580 に答える
1

わたしにはできる:

#include <iostream>

class foo
  {
public:
  int g (int x, int y) { return x + y ; }
  } ;

typedef int (foo::*memberf_pointer)(int, int);

int main()
  {
  foo f ;
  memberf_pointer mp = &foo::g ;
  std::cout << (f.*mp) (5, 8) << std::endl ;
  }
于 2011-01-28T21:24:40.017 に答える
1

現在の構文で機能しない理由は、演算子の優先順位により、foo::memberf_signature任意の種類の型ではなく、という名前の関数を参照していることが示されるためです。

これができるかどうかはわかりませんが、コードを g++ 4.2 でコンパイルするように誘導する括弧の組み合わせを思いつきませんでした。

于 2011-01-28T19:57:13.880 に答える
-3

基本的には機能しません (少なくとも g++ を使用する方法はわかりません)。Borland C++ コンパイラを使用すると、__closure キーワードが存在します。

コンパイルされない理由は、関数ポインタのサイズ (x86 マシン上) が常に <<32 ビット>> を占めるためです。ただし、クラス (インターフェイス) シグネチャをポイントする場合は、sizeof を 64 ビットにする必要があります。このポインターの場合は 32 ビット (クラス インターフェイスは一度だけメモリ内にあるため)、実際の関数の場合は 32 ビットです。

しかし、__closure キーワードは標準化されていない bcb 言語の「ハック」です...

于 2011-01-28T20:08:17.613 に答える