クラスは、関数ポインタの夢を見るか?
関数ポインタを利用したテーブル化は、
非常に使い出がある…
と、ボケは、考える…。
例えば、こんなテーブルを作れる。
WEAPON WeaponList[] =
{// 名称,属性,説明,破壊力,価格,処理
"村正宗","刀","邪悪なものを両断できる。",100,1000,FunctionKatana,
"GLOCK 18C","銃","取り使い易いハンドガン。",100,1000,FunctionGun,
NULL,
};
文字列や値、処理を一つにまとめる事が出来る。
情報がまとまっているのでチェックし易いし
項目の追加と削除もし易い!
以下の処理では、「switch」と比較してみる…。
#include<stdio.h>
void Function0(void){printf("0\n");}
void Function1(void){printf("1\n");}
void Function2(void){printf("2\n");}
//--------------------------------------
struct TEST
{
void(*Function)(void);
}test[]=
{
Function0,
Function1,
Function2,
NULL,
};
//--------------------------------------
void main(void)
{
int i;
// スイッチなら…。
for(i=0;i<3;i++)
{
switch(i)
{
case 0:Function0();break;
case 1:Function1();break;
case 2:Function2();break;
}
}
// 関数ポインタなら…。
for(i=0;test[i].Function!=NULL;i++)
test[i].Function();
}
実際、関数ポインタの方が「switch」より早い。
しかし、たまにコンパイラの最適化で
同等の速度に成る事が有るが…
それは、プログラマーが意図とした結果で無いので
必ずなるわけでもない…。
また、色々な情報をパックするのが
「switch」だと面倒…。<こいつを言いたかった…。
と
有用性を説いた所で!
この便利なやり方が、
クラスだとうまく出来ない…。
…。
これは、クラスは、仮想である…
つまり実体が無い…
よってクラスのメンバー関数には、
確定したアドレスがない…。
…。
だから、テーブル化できない…。
…。
テーブル化する際には、実数(確定した値)が必要
ということらしい…。
…。
が、クラスのメンバー関数に
実体を持たせる方法が
ある…。
そいつは、「static」を使うのだが…。
#include<stdio.h>
#include<stdlib.h>
//--------------------------------------
class TEST
{
public:
int a;
static void Function0(TEST*test){printf("0-%02d\n",test->a);test->a+=10;}
static void Function1(TEST*test){printf("1-%02d\n",test->a);test->a+=10;}
static void Function2(TEST*test){printf("2-%02d\n",test->a);test->a+=10;}
void Function3(void){printf("%d .........\n",a);};
typedef struct List
{
void(*Function)(TEST*test);
}LIST,*LPLIST;
static LIST List[];
TEST()
{
a=0;
}
};
//--------------------------------------
TEST::LIST TEST::List[]=
{
Function0,
Function1,
Function2,
NULL,
};
//--------------------------------------
void main(void)
{
class TEST test;
int i;
for(i=0;test.List[i].Function!=NULL;i++)
test.List[i].Function(&test);
test.Function3();
}
実体化したのは、良いのだが…
この静的メンバー関数は、
仮想の動的メンバー変数には
アクセスできない…。
なんてっこった!!
よって、仮想のメンバー変数にアクセスするには
引数に自身のクラスが必要となる…。
おお、ただの関数のようだ…。
実にスマートでない!
が、取り合えず目的は、達成できた…。
…。
クラスのメンバー関数も当然通常の関数と同じ様に
メモリー上にマップされている。
だからアドレスが取れるはずだが…?
クラスの場合には、メンバー関数の呼び出し口から
関数の実態を呼び出す。
つまり、リンクを介してアクセスする形なのだ…。
このリンク先を書きかえることで
アクセスする関数を切り替えることが出来る仕組みなのだが…。
何とか、もっとスマートな方法で対処したい!
と、C++の仕様と格闘したのだが!
…。
ごめんなさい。
負けました…。
| 固定リンク
コメント