Borland C++ Builderの__closureの意味を知った。__closureを使うと、所属するクラスによらないメンバ関数ポインタを作ることができる。つまり、戻り値と引数の形式が同じ関数ならば、どのクラスの関数でも代入できる関数ポインタをつくることができる。
class A { public: int foo(int, double); }; class B { public: int hoge(int, double); }; int (__closure *fp)(int i, double d); //関数ポインタ定義 A* pA = new A; B* pB = new B; fp = pA->foo; //代入できる fp = pB->hoge; //代入できる
__closureは、VCLのイベントハンドラに欠かせない。たとえば、VCLオブジェクト(ボタンなど)がクリックされたときの処理は次のように登録する。
- 実行させたい処理を行う関数を作る。(通常は、メンバ関数)
- その関数のアドレスをthis->OnClickに代入する。
OnClickプロパティは親クラス()で宣言されている関数ポインタなので、本来なら子クラスのメンバ関数を代入することはできない。OnClickの定義時には子クラスの型は決まっていないからだ。ところが__closureを使ってOnClickが定義されていればこのような代入が可能になる。代入したポインタから関数を実行することも当然できる。VCLのイベントハンドラはこのような仕組みになっているようだ。
__closureを使うことで、戻り値と引数さえ同じであれば、TFormのメンバ関数であろうと独自のクラスのメンバ関数であろうとまったく同じに扱うことができる。この機能は自分でコールバックを実装するときに非常に便利だ。
うーん、早く調べていればコールバックをもっと楽に実装できたのに。知らなかったがために、わざわざクラステンプレートを使ったりややこしい実装をしてしまった。おかげでコードも複雑になってしまってるから__closureを使って書き直したいなあ。どうしよう。書き直す手間もさることながら、__closureはBorland C++独自の機能なので移植性も悪くなるのもちょっと気になるし。
それにしても__closureや__propertyなどの、Borlandの独自拡張はかなり便利。C++標準仕様に取り入れられれば移植性を気にしなくて済むのに。