« なんとなくプラモデルメイク!(ケロロ軍曹の場合…) | トップページ | 風邪をひいてます…。 »

2005年10月 8日 (土)

クラスは、関数ポインタの夢を見るか?

関数ポインタを利用したテーブル化は、
非常に使い出がある…

と、ボケは、考える…。

例えば、こんなテーブルを作れる。

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++の仕様と格闘したのだが!

…。

ごめんなさい。
負けました…。

|

« なんとなくプラモデルメイク!(ケロロ軍曹の場合…) | トップページ | 風邪をひいてます…。 »

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック


この記事へのトラックバック一覧です: クラスは、関数ポインタの夢を見るか?:

« なんとなくプラモデルメイク!(ケロロ軍曹の場合…) | トップページ | 風邪をひいてます…。 »