2017-10-19 2 views
2

で定義されたポインタを介して、クラスメソッドを呼び出す場合には、私は次のように定義されたクラスがあります主な機能で構文そのクラス

class A 
{ 
public: 
    A() 
    { 
     fp = &A::f; 
    } 

    void (A::*fp)(); 

    void f() 
    { 
     cout << "A::f()" << endl; 
    } 
}; 

を、Iは、定義されたクラスAのオブジェクトがあり、Iは呼び出したいです.fp()。しかし、私はa.fp()でも(a.fp)()でもこれを行うことができないことを知りました。最後に、構文の観点から全く奇妙な(a.*a.fp)()が働いていました。

int main() 
{ 
    A a; 
    (a.*a.fp)(); 

    return 0; 
} 

は、誰もが (a.*a.fp)()が実際に何を意味するのか説明してもらえ、なぜ (a.fp)()動作しませんか?

+0

与えられたAインスタンス(あなたの例では 'a')で' a.fp'を得るために一度、そして 'fp'を呼び出すために二度目に' a'を2回アクセスする必要があります。 – rustyx

答えて

5

はのグループ化を明示的にするために括弧を追加してみましょう:

(a.*(a.fp))() 
  1. a.fpは、ポインタ・ツー・メンバーfpa内部への定期的なアクセスです。
  2. a.*(...)は、メンバーアクセス演算子へのポインタを使用して間接的にメンバー関数を取得します。

  3. (...)()は、(...)の "callable"式の関数呼び出しを実行します。

なぜ(a.fp)()は機能しません。メンバーへのポインタは通常のポインタと似ていないからです。それらをクラスのインスタンスであるオブジェクトに適用する必要があります。したがって、a.fpは、それ自身の呼び出し可能な型ではないメンバへのポインタのみを取得します。呼び出し可能な式を生成するには、.*によって達成されるオブジェクトに適用せずに呼び出すことはできません。

1

このコードは、2つの異なる目的のために、2つの異なる方法でaオブジェクトにアクセスします。それをよりよく理解するには、2つを分離する必要があります。ポインタメンバ関数を使用してメンバ関数を呼び出す

は、あなたが実際のオブジェクトまたはオブジェクトへのポインタを持っているかどうかに応じて、.*または->*のいずれかが必要です。

void (A::*afp)() = &A::f; 
A a; 
(a.*afp)(); // calls A::f on the `a` object 
A* ap = &a; 
(ap->*afp)() // calls A::f on the `a` object 

へのポインタ-member-functionは、通常のクラスメンバーアクセスでポインターにアクセスする必要があるクラスのメンバーです。つまり、a.fpはオブジェクトaのメンバー関数へのポインタです。したがって、2つを組み合わせると、(a.*a.fp)()は、aというメンバ関数を呼び出し、a.fpはを指し、aオブジェクトでそれを呼び出します。

1

a.fpは、メンバ関数へのポインタです。「ポインタ」は、「オブジェクトに基づくある種のインダイレクション」という非常に一般的な意味で理解されます。
ポインタにはAのインスタンスについての知識がありません。オブジェクトは相対的に参照解除できるオブジェクトが必要です。
つまり、aも必要です。

aに対する任意のメンバーポインタpを参照解除すると、a.*pのようになります。
.*は2つの演算子のように見えますが、実際には1つのみ、「ポインタへのデリファレンス演算子」です)。
メンバ関数のポインタがa.fpであるため、逆参照構文はa.*(a.fp)以上、つまりa.*a.fpです。

その後、あなたは(優先順位の理由で)カッコ内にその束をラップする必要があり、

(a.*a.fp)() 

サイドノートを取得:以下も有効です。

void (A::*function)() = &A::f; 
A a; 
(a.*function)(); 
A b; 
(a.*b.fp)(); 

と同じことを行います。

1
(a.*a.fp)(); 
    a   the instance a 
    a.fp  the member of a which is a pointer to member function 
    *a.fp  dereferencing the member function pointer 
(a.*a.fp)() invoking the member function on a 

最後の2つのステップは実際には1つです(.*は1つの演算子です)。 mem_funがメンバーfucntionポインタである場合、一般的には、それを呼び出すための構文は

(a.*mem_fun)(); 

here参照されます。

関連する問題