> あ、もしかして"*f"の部分は"f"という変数ではなく"FuncTbl[0][0]"
> そのものを指してるという事なるのでしょうか。
(関数型への)ポインタ型のf という変数に関数のアドレスを
コピーしています。
> 自前の解釈だと、事前のAというクラスの宣言では"f"というメンバは
> 無いのに、Execute()の中で(a.*f)という表記がされているのが理解でき
> ないんです。
C互換の「ポインタを介しての関数の実行」からこんがらがっているのでしょう。
まず、メンバという条件をなくして理解してみましょう。
001: void someFunc( int a ) {
002: cout << "value : " << a << endl;
003: }
004:
005: typedef void (*FP_t)( int );
006:
007: int main(void) {
008: FP_t ptrFunc;
009: ptrFunc = &someFunc;
010:
011: (*ptrFunc)( 2 );
012: ptrFunc( 2 );
013: }
5行目で"関数へのポインタ"という型を定義しています。
8行目でその"関数へのポインタ"という型の***変数***を宣言しています。
9行目でその変数にsomeFuncのアドレスを***コピー***しています。
11,12行目でその関数ポインタを介して、関数そのものを実行しています。
この11,12行目は実は同じ事をしていますが、なぜ2つの書き方があるか
というと、Cライクな書き方とC++ライクな書き方です。
本当は11行目のようにして実行することがC++では正しいのですが、
Cでは「関数名=関数アドレス」という考え方でしたので、その下位互換を
保つ為、12行目のような書き方も許されています。
# 文法的には、12行目が「暗黙のポインタ変換」され11行となります。
C++では、厳密に 「ポインタ=宣言のアドレス」なわけです。
まとめ 関数 変数
------------------------+-----------------------------------+-----------
1)xxxの定義 | 戻り型 関数名(引数) { .... } | 型名 変数名
2)xxxのアドレス | & 関数名 | & 変数名
3)xxxへのポインタ型 | 戻り値 * 関数名(引数) | *型名
4)ポインタを介しての実体| *関数名 | *変数名
C C++
--------------------+---------------------------+-------------------------
a)関数名 |関数名 | 関数名
b)関数の型 |関数名(引数) | 関数名(引数)
|だが型チェックなしにもでき |
|厳密な意味では存在しない |
c)関数のアドレス |関数名 | &関数名
d)関数へのポインタ型|*関数の型 | *関数の型
e)関数の実体 |関数名(引数){ ... } |関数名(引数){ ... }
g)関数の実行 |関数名( ... ) |
(*ptrFunc)とすることによって「ポインタから(関数の)実体を取得」し、
その実体に(2)という関数呼び出し演算子を作用させることによって
関数を実行しているわけです。
つまり、Cで関数アドレス=関数名とおかしな文法を持ち込んでいたのを
ただしたわけです。
そして、C++における関数の実行とは関数の実体に関数呼び出し演算子を
付けたものとなり、「実体の評価」となって、変数と対照が取れるわけです。
# 評価により、値が確定し、(左辺値でなく)右辺値となります。
見事に変数との対照が取れ、直行性が出来ています。
ちなみに、変数に型があるように、関数にも型があり、それは関数名に
引数リストを付けたものとなっています。
そう考えると、3)は型名の前に*を付けた物として対照が取れます。
ここまでの文法が理解できたならば、あとはこれに「クラス」の概念を
付ける為にスコープ解決演算子"::"とメンバ参照演算子"."を合わせればOKです。
上記のコードがそのまま
001: void SomeClass::someFunc( int a ) {
002: cout << "value : " << a << endl;
003: }
004:
005: typedef void (SomeClass::*FP_t)( int );
006:
007: int main(void) {
008: FP_t ptrFunc;
009: ptrFunc = &SomeClass::someFunc;
010: SomeClass a;
011: (a.*ptrFunc)( 2 );
012: // a.ptrFunc( 2 );
013: }
となります。
残念ながら、クラスはC++のみの概念なので、クラスメソッドの実行
(クラスメンバへのアクセス)はC++での表記しかサポートされておらず、
12行目のような記述は出来ません。
上記が理解できれば、メンバ関数へのポインタが配列に入っているので、
> > Func f = FuncTbl[0][0];
>
> ここで宣言した、Aクラスのメンバ(関数)へのオフセット(ポインタ)です。
> > (a.*f)();
は理解できるのではないでしょうか?
*メニュー
最新の20件
2018-04-17
2012-01-07
2011-12-07
2011-11-03
2011-10-20
2011-10-18
2014-07-13
2013-08-10
2012-01-26
2012-01-25
2012-01-24
2012-01-23
2012-01-21
2012-01-20
2012-01-19
2012-01-17
2012-01-14
2012-01-13
2012-01-09
人気の10件
- counter: 1398
- today: 1
- yesterday: 0
- online: 5