動的にキャスト またはテーブルを作成をしたい – プログラミング – Home

動的にキャスト またはテーブルを作成を...
 
通知
すべてクリア

[解決済] 動的にキャスト またはテーブルを作成をしたい

固定ページ 1 / 2

任たま
 任たま
(@任たま)
ゲスト
結合: 22年前
投稿: 10
Topic starter  

 型の種類を保持して 内部でその型にキャストするようなものを
 創ることは可能でしょうか?

 switch文で番号をみてキャストするような方法はできればやりたくないです。


引用未解決
トピックタグ
ナオーバ
 ナオーバ
(@ナオーバ)
ゲスト
結合: 23年前
投稿: 187
 

何を言わんとしているかわかりません。

型の種類を保持して-->何に保持?
内部でその型にキャスト-->何の内部?
switch文で番号をみて-->何の番号?

できれば詳しくお願いします。


返信引用
YuO
 YuO
(@YuO)
ゲスト
結合: 22年前
投稿: 320
 

キャストして何がしたいのですか?

仮想関数とか,intのIDと関数ポインタとか,目的によっ
ては方法が存在すると思います。


返信引用
任たま
 任たま
(@任たま)
ゲスト
結合: 22年前
投稿: 10
Topic starter  

関数のポインタを保持して呼ぶようにしているのですが、
  現在は 下記の型の関数しか呼ぶことができません。
  
  int (*FuncAddress)(int *pObject);

それを 
  Regist(aaa, 引数の型);  aaaの関数ポインタを登録
    Regist(bbb, 引数の型);  bbbの関数ポインタを登録
 
みたいな書き方をして
    (int *pObject) の部分を動的に変えられたらとおもっています。
   
  int aaa(int a){

return 0;
}

  int bbb(char b){

return 0;
}

  switch文などで 0番はint型変換 ,1番はchar型変換・・・・
  などを 手作業で追加していくようなことをやらずにできたらなと
  思っています。   
   
   


返信引用
PAI
 PAI
(@PAI)
ゲスト
結合: 23年前
投稿: 359
 

実際にその関数を呼ぶときの引数はどこから来るんでしょう、
登録時にいっしょに登録するんでしょうか?呼ぶときにどこかから与えられるんでしょうか?

実際に関数を呼ぶときに引数が必要で、なおかつその引数の型が違うなら、
いずれにせよどこかで無理が生じると思うんですが・・・個人的に。

汎用のものであれば、operator() を仮想関数にして規定クラスを作り
そこからテンプレートで関数ポインタの型ごとに派生させてやることで
できなくはないですけど、費用対効果が低いかと。

Andrei Alexandrescu の ModernC++Design(Loki) でやってます。
http://www.moderncppdesign.com/

それほど汎用的でなくていいなら、この例でいくと必ず戻り値はintっぽいし、
引数もポインタっぽいので、とりあえずvoidポインタで渡して使う側で切り分けるとすると、
こんな感じでしょうか?

struct FuncBase{
virtual int Execute( void* p )=0;
};

template<typename T>
struct Functor: public FuncBase {
int (*m_Func)( T* );

int Execute( void * p ){
return m_Func( static_cast<T*>(p));
}
};

template<typename T>
Functor<T>* MakeFunctor( int (*funcPtr)(T*)){
Functor<T>* pRet = new Functor<T>();
pRet->m_Func = funcPtr;
return pRet;
}

int a( int * p ){
cout << int: << *p << endl;
return 0;
}

int b( char* p ){
cout << char: << *p << endl;
return 0;
}

int main(int argc, char* argv[])
{
vector<FuncBase*> funcs;
funcs.push_back( MakeFunctor(a));
funcs.push_back( MakeFunctor(b));

int i;
int buff = 0x12345678; // int として扱われたり char として扱われたり。

for( i =0; i<funcs.size() ;i++){
funcs[i]->Execute(&buff);
}

for( i = 0; i<funcs.size() ;i++){
delete funcs[i];
}
return 0;
}


返信引用
任たま
 任たま
(@任たま)
ゲスト
結合: 22年前
投稿: 10
Topic starter  

>実際にその関数を呼ぶときの引数はどこから来るんでしょう、
>登録時にいっしょに登録するんでしょうか?呼ぶときにどこかから与えられるんでしょう
>か?

 Functorのメンバの中に ポインタを用意しておいて、どこかで領域を確保し、
 それを、切り分けて 登録した関数に渡してあげようと思っています。
 
pDataで 確保された領域を 実際どの程度使われて、あと残りどのくらい
  あるかを 調べることができないと駄目なので、型の種類を保持できないと  
  やりたいことができないかもしれません。  何か方法ありますでしょうか?
 
template<typename T>
struct Functor: public FuncBase {

  char *pData;

int (*m_Func)( T* );

int Execute( void * p ){
return m_Func( static_cast<T*>(p));
}
};


返信引用
PAI
 PAI
(@PAI)
ゲスト
結合: 23年前
投稿: 359
 

>Functorのメンバの中に ポインタを用意しておいて、どこかで領域を確保し、
>それを、切り分けて 登録した関数に渡してあげようと思っています。

『どこか』ってここでいうFunctorの外で、ですか?
それはちょっときついんじゃないかと。

領域の確保、チェック、開放などを行う関数全体を関数テンプレートから作らせれば
出来なくはなさそうですけど…(パズル的にやってしまう人はいそう、という意味で)

型ごとに切り分けて行うオペレーションをすべてまとめた状態でクラステンプレートを作って
そこから型ごとに実体化させてやる必要があります。

最終的にどういった要求があるのかがちょっとわからないのでなんともいえませんが、
void* と 確保したい型の sizeof をとっておくなどして、
型識別子とかを用意して、適宜switch等で分けるのが結局1番楽かもしれません。

そういった要求が必要になるシチュエーションがすぐには浮かんでこないのですが、
あるいはもしかしたら、もっと高いレベルでのつくりを見直す必要があるのかもしれません。


返信引用
任たま
 任たま
(@任たま)
ゲスト
結合: 22年前
投稿: 10
Topic starter  

>switch等で分けるのが結局1番楽かもしれません。

そうなのですが、使わずにやりたいです。
 今日 c++の本を読んでいましたら、
 type_info の typeid().nameで 型名の取得できるので、
 そこから、なんとか、型変換に持っていけないかなと考えています。

>『どこか』ってここでいうFunctorの外で、ですか?
 書き方がまずかったですね。
 どこかというのは、 あくまで、クラスの中での話です。
 
 確保するサイズを保持しておいて
関数ポインタが初めて登録されたときに、内部で確保するか、
 外で、確保する関数を呼んでもらうかは まだ決めていません。
 


返信引用
PAI
 PAI
(@PAI)
ゲスト
結合: 23年前
投稿: 359
 

>type_info の typeid().nameで 型名の取得できるので、
>そこから、なんとか、型変換に持っていけないかなと考えています。

無理です。それを『コンパイラが』知る手段がありません。

ちょっと何がしないのかが見えてきません。

ここでいうFunctorの中なら、
テンプレートパラメータの T が引数で与えられたポインタのpointeeの型になりますけど。


返信引用
PAI
 PAI
(@PAI)
ゲスト
結合: 23年前
投稿: 359
 

/s 何がしない 何がしたい

失礼。


返信引用
任たま
 任たま
(@任たま)
ゲスト
結合: 22年前
投稿: 10
Topic starter  

PAIさん、ちょっとわからないことがあるので教えていただけませんでしょうか?

この PAIさんが書かれたソースで Functor<T>の型でnewしていますが、
delete するときは FuncBaseの型になってますよね。
これってきちんと解放してくれるのですか?

 Functor構造体のほうがint (*m_Func)( T* );サイズ分大きいのできちんと解放できない
 ように思いますが・・・・
 
struct FuncBase{
virtual int Execute( void* p )=0;
};

template<typename T>
struct Functor: public FuncBase {
int (*m_Func)( T* );

int Execute( void * p ){
return m_Func( static_cast<T*>(p));
}
};

template<typename T>
Functor<T>* MakeFunctor( int (*funcPtr)(T*)){
Functor<T>* pRet = new Functor<T>();
pRet->m_Func = funcPtr;
return pRet;
}

int main(int argc, char* argv[])
{
vector<FuncBase*> funcs;
funcs.push_back( MakeFunctor(a));
funcs.push_back( MakeFunctor(b));

int i;
int buff = 0x12345678; // int として扱われたり char として扱われたり。

for( i =0; i<funcs.size() ;i++){
funcs[i]->Execute(&buff);
}

for( i = 0; i<funcs.size() ;i++){
delete funcs[i];
}
return 0;
}


返信引用
PAI
 PAI
(@PAI)
ゲスト
結合: 23年前
投稿: 359
 

ほんとだ、まずいね。ごめんなさい。
『ポリモーフィックに使用するクラスのデストラクタはvirtualに』
しとかなきゃあかんですな。

ってことで
virtal ~FuncBase() = 0;

とでも付け加えておいてください。


返信引用
任たま
 任たま
(@任たま)
ゲスト
結合: 22年前
投稿: 10
Topic starter  

PAIさま、お世話になっております。

調べてみたのですが、わからなかったので教えていただけませんか?
>virtal ~FuncBase() = 0;
この書き方はうまくいきますか?
いろいろ試してみたのですが、エラーがでてしまって、できませんでした。
virtal ~FuncBase(){};
は大丈夫なのですが・・・・

それと、これを仮想関数にすることによりどのようにかわるのでしょうか?
delete をした時に、きちんと派生クラスのサイズ分解放してくれるのでしょうか?
それとも、

~Functor(){

}


返信引用
任たま
 任たま
(@任たま)
ゲスト
結合: 22年前
投稿: 10
Topic starter  

PAIさま、お世話になっております。

調べてみたのですが、わからなかったので教えていただけませんか?
>virtal ~FuncBase() = 0;
この書き方はうまくいきますか?
いろいろ試してみたのですが、エラーがでてしまって、できませんでした。
virtal ~FuncBase(){};
は大丈夫なのですが・・・・

それと、これを仮想関数にすることによりどのようにかわるのでしょうか?
delete をした時に、きちんと派生クラスのサイズ分解放してくれるのでしょうか?
それとも、

~Functor(){

}
の中で何かを書くことで正しく解放できるようになるということなのでしょうか?


返信引用
PAI
 PAI
(@PAI)
ゲスト
結合: 23年前
投稿: 359
 

>>virtal ~FuncBase() = 0;
>この書き方はうまくいきますか?
FuncBase::~FuncBase() の実体をどこかで作ってあげればいける。
クラス定義内で
>virtal ~FuncBase(){};
でもOK。

>それと、これを仮想関数にすることによりどのようにかわるのでしょうか?
ちゃんと派生先のデストラクタが呼ばれてくれる。
operator delete も派生先が適応されてしっかり派生先のサイズ分開放される。


返信引用
固定ページ 1 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました