web-dev-qa-db-ja.com

メンバー関数ポインターを使用したtypedef構文

mSDNによると、typedef構文は次のとおりです。

typedef type-declaration synonym;

非常に簡単:

typedef int MY_INT;

しかし、メンバー関数ポインターのtypedefはこの規則にどのように準拠しているのでしょうか。

typedef int (MyClass::*MyTypedef)( int);

100%混乱–同義語(MyTypedef)が真ん中にある?

誰かが、MSDNの非常に理解しやすい構文形式から、上記のtypedefの逆/ランダム/フロント/ラスト/混合構文に至るまでの論理的な手順を説明できますか?

*すべての高速回答(および私の投稿の美化)に感謝を編集:)

26
muxmux

同義語(MyTypedef)は真ん中にありますか?

真ん中にはありません。しばらくメンバー関数を忘れて、関数ポインターがどのように定義されているかを見てください:

int (*FuncPtr)(int);

そして、これはあなたがそれをtypedefする方法です:

typedef int (*FuncPtr)(int); 

シンプル!唯一の違いは、typedefではFuncPtrtypeになるのに対し、ポインタ宣言ではFuncPtrvariableになります。

同様に、

int (MyClass::*MyTypedef)( int); //MyTypedef is a variable

そしてtypedefは次のようになります:

typedef int (MyClass::*MyTypedef)( int); //MyTypedef is a type!
37
Nawaz

C++ 11以降、この式を読みやすいusingステートメントとして記述できることに注意してください。

using MyTypedef = int (MyClass::*)(int);
17
kfsone

メンバー関数へのポインターをどのように定義しますか?このような:

int (A::*variableName)(int);

Typedefにするには、typedefを追加するだけです。

typedef int (A::*typedefName)(int);
10
ybungalobill

C++での宣言の原則は、それらが使用法を模倣することです。メンバー関数pmfへのポインターを使用する場合は、次のように記述します。

(myVar.*pmf)(arg);

typedefを定義するには、次のように記述します。

typedef int (MyClass::*pmf)(int);

先頭に戻りの型を追加し、変数を型に、引数を型に置き換えます。

4
AProgrammer

私はあなたがすでにあなたの答えを得たことを知っていますが、これを共有したいのです-それは便利です http://www.cdecl.org 。 C/C++宣言<->英語翻訳者です。入力するだけ

クラスAのメンバーへのポインターとしてxを宣言します(int)charを返します

そしてchar (A::*x)(int )を取得します。または、宣言をいじって、必要なものが得られるかどうかを確認します。

4
davka

メンバー関数ポインターを使用する構文は、次のようにする必要があります(aはクラスAのインスタンスであると想定):

  • 宣言では、接頭辞として「A ::」を使用します
  • 使用する場合は「a」を使用してください。接頭辞として

以下はおもちゃの例です。あなたはそれで遊ぶことができます。

#include <stdio.h>
#include <stdlib.h>
class A;
typedef int (A::*F)(double);

class A {
 public:
  int funcDouble(double x) { return (int)(x * 2.0); }
  int funcTriple(double x) { return (int)(x * 3.0); }

  void set(int a) {
    if (a == 2) {
      this->f_ = &A::funcDouble;
    } else if (a == 3) {
      this->f_ = &A::funcTriple;
    } else {
      this->f_ = NULL;
    }
  }

 public:
  F f_;
};
int main(int argc, char *argv[]) {
  A a;
  a.set(2);
  F f = &A::funcDouble;
  printf("double of 1 = %d\n", (a.*f)(1));

  // Below is equivalent to:
  // F f2 = a.f_;
  // printf("double of 1 = %d\n", (a.*f2)(1));
  printf("double of 1 = %d\n", (a.*(a.f_))(1));

  a.set(3);
  printf("triple of 1 = %d\n", (a.*(a.f_))(1));

  return 0;
}
3
zhanxw

あなたが参照しているページは、おそらく " typedef Specifier "です。単純化された "typedef type-declaration synonim; "構文はtypedefを使用する多くの方法の1つにすぎません。typedefの使用方法を説明する単純で簡潔な方法は(おそらく)ありません。それが" Typedef Declarations "MSDNページです。のためです。

このページでは次のように気づくでしょう:

declaration: 
    declaration-specifiers init-declarator-list opt ; 
declaration-specifiers: 
    storage-class-specifier declaration-specifiers opt 
    type-specifier declaration-specifiers opt
    type-qualifier declaration-specifiers opt 
storage-class-specifier: 
    typedef

どの宣言宣言子とinit-declarator-listが見つかるかについての詳細 here

これは、「typedef」のすべての可能な使用法を理解するための1つの厳密な方法です。

このページで基本的に言っているのは、「typedef」はほとんどの有効な宣言の前に使用できるということです。

1
Nick

私は一度素敵な説明を読んだことがあります(しかし、それは Expect C Programming からのものなので、私はymmvです):

実際、typedefの形式は変数の宣言とまったく同じですが、このキーワードを追加するだけでヒントになります。

Typedefは変数宣言とまったく同じように見えるので、変数宣言とまったく同じように読み取られます。 「この名前は指定されたタイプの変数を参照しています」と宣言する代わりに、typedefキーワードは変数を作成しませんが、「この名前はの同義語です。指定されたタイプ。」

だからあなたはそれを持っています。変数を宣言していると想像してみてください。変数の前にtypedefを付けておくと、新しい型になります。 MSDN説明は混合されたバッグです:私は本当に神のものと全く悪いものを読みました。

1
cnicutar

次のように考え始めると、理解しやすくなります。

次のような関数が見つかるときはいつでも:

TYPE foo(int arg1, int arg2);

FooのタイプはTYPEであると言います。したがって、タイプ

int get_next_prime();

intです。

関数ポインタを関数の引数として渡すと、次のことがわかります。

void register_callback(void (*ptr)(int));

この場合、タイプvoidの関数を引数として渡します。

今、あなたはそのようなものを見たとき:

typedef int (A::*typedefName)(int);

変数(A :: * typedefName)(int)(これは関数ポインタ宣言であるため、2つではなく1つだけです)は実際にはint型であると言っているだけです。それ以降、コンパイラはA :: * typedefNameをint型の関数として解釈します。つまり、int値を返します。

混乱が少なくなることを願っています。

0