アットウィキロゴ

11月14日(2008)


C++/CLIでのクラスのメンバ関数の関数テーブル作成

メンバ関数をテーブル化して呼び出そうと思い、色々やってみたが一筋縄ではいかなかった。

ref class Form { 
   int func_0( void );
   int func_1( void );
}

というシグネチャの関数をテーブル化しようとして、まずは
Cの関数テーブル作成の要領で、確実に駄目だろうと思いつつも

array<int (*func[])(void)> ^func_tbl;

としてみる。見るからにダメだろ、常識的に考えて…という予想どおり、アウト。
しかし、

typedef int (*MethodPointer)(void);

と、一旦関数ポインタをMethodPointerという名前にしておき、

array<MethodPointer> ^func_tbl;

func_tbl = gcnew array<MethodPointer>(2);

とするとコンパイルは通る。
しかし、クラス外の MethodPointer型の関数を登録する分には問題は生じず、
普通に関数ポインタテーブルとしての人生を謳歌できるのだが、
MethodPointer型のメンバ関数を登録しようとするとコンパイラに怒られる。
こんな感じで。

NameSpace::Form::Func': 関数呼び出しには引数リストがありません。
メンバへのポインタを作成するために '&NameSpace::Form::Func' を使用してください

※NameSpaceは大元のネームスペースです。

なので、コンパイラの言われるまま、&NameSpace::Form::Func をセットしてやろうと思いやってみると

delegate インスタンスを作成する場合以外に、'NameSpace::Form::Func' のアドレスを指定できません

という追い討ちをかけられる事になる。
結局のところ、メンバ関数ポインタを保持したいんだったらデリゲートを使ってね、という事のよう。

デリゲートは複数の関数を登録でき、Invoke()で一括処理できるので便利!とも思ったが、
登録してある関数を指定して実行とか、途中で条件分岐で処理を止めるとかは別のお話といった
感じなので、結局はデリゲートの配列を持つことに…。
最終的にはこんな感じ。

delegate int FuncIntVoid( void );  // クラスの外での宣言

// クラス宣言
ref class Form {
   array<FuncIntVoid^>	^m_FuncTbl;
   
   int Func_0( void );
   int Func_1( void );
};

// テーブル作成
m_FuncTbl = gcnew array<FuncIntVoid^>{
   gcnew FuncIntVoid( this, &Form::Func_0 ),
   gcnew FuncIntVoid( this, &Form::Func_1 ),
}

// 実行
for( int i = 0; i < m_FuncTbl->Length; i++ ) {
   m_FuncTbl[i]->Invoke();
}

こんな感じでイケる。
注意が必要なのは、メンバ関数の登録の際には第1引数に送り元となるthis
指定しなければならないということ。メンバ関数ではなく、どっかのグローバル関数を
登録したりするときは必要ない。

…という感じで実装してみたが、なんかスマートじゃない気が…。
もっと他にやり方あるんじゃないかな。



日付とか時間の管理とか

VBだとDate型の環境が非常に整っており、比較的簡単に日付の操作とかができるのだが、
C++/CLIにはないのかね?という事で自作してみた。

※.NET FrameworkクラスライブラリにSystem::DateTime構造体ってのがあって、
 これを使えばいいんじゃないかという話も…。
 ただ、使うにしてもマネージクラスにしか使えないので、アンマネージオブジェクト内で
 使うにはやはり自作なのか…。

time_t型、tm構造体を主として使う。
time_t型は時間の保持として使い、tm構造体はtime_t型に時間をセットするのに使う。
tm構造体の各メンバ(年、月、日、etc...)に値をセットし、
mktime()でセットする感じだ。

time_t -> tm への変換は localtime() を使って行う。
gmtime() を使ったせいで、世界協定時刻を取得し、毎回9時間の時差に悩まされたというのは内緒だ…。

とりあえず、時間の加減算、取得、セットなどができるクラスを作っている最中。
最終更新:2008年11月14日 13:36
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。