型の種類を保持して 内部でその型にキャストするようなものを
創ることは可能でしょうか?
switch文で番号をみてキャストするような方法はできればやりたくないです。
何を言わんとしているかわかりません。
型の種類を保持して-->何に保持?
内部でその型にキャスト-->何の内部?
switch文で番号をみて-->何の番号?
できれば詳しくお願いします。
キャストして何がしたいのですか?
仮想関数とか,intのIDと関数ポインタとか,目的によっ
ては方法が存在すると思います。
関数のポインタを保持して呼ぶようにしているのですが、
現在は 下記の型の関数しか呼ぶことができません。
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型変換・・・・
などを 手作業で追加していくようなことをやらずにできたらなと
思っています。
実際にその関数を呼ぶときの引数はどこから来るんでしょう、
登録時にいっしょに登録するんでしょうか?呼ぶときにどこかから与えられるんでしょうか?
実際に関数を呼ぶときに引数が必要で、なおかつその引数の型が違うなら、
いずれにせよどこかで無理が生じると思うんですが・・・個人的に。
汎用のものであれば、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;
}
>実際にその関数を呼ぶときの引数はどこから来るんでしょう、
>登録時にいっしょに登録するんでしょうか?呼ぶときにどこかから与えられるんでしょう
>か?
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));
}
};
>Functorのメンバの中に ポインタを用意しておいて、どこかで領域を確保し、
>それを、切り分けて 登録した関数に渡してあげようと思っています。
『どこか』ってここでいうFunctorの外で、ですか?
それはちょっときついんじゃないかと。
領域の確保、チェック、開放などを行う関数全体を関数テンプレートから作らせれば
出来なくはなさそうですけど…(パズル的にやってしまう人はいそう、という意味で)
型ごとに切り分けて行うオペレーションをすべてまとめた状態でクラステンプレートを作って
そこから型ごとに実体化させてやる必要があります。
最終的にどういった要求があるのかがちょっとわからないのでなんともいえませんが、
void* と 確保したい型の sizeof をとっておくなどして、
型識別子とかを用意して、適宜switch等で分けるのが結局1番楽かもしれません。
そういった要求が必要になるシチュエーションがすぐには浮かんでこないのですが、
あるいはもしかしたら、もっと高いレベルでのつくりを見直す必要があるのかもしれません。
>switch等で分けるのが結局1番楽かもしれません。
そうなのですが、使わずにやりたいです。
今日 c++の本を読んでいましたら、
type_info の typeid().nameで 型名の取得できるので、
そこから、なんとか、型変換に持っていけないかなと考えています。
>『どこか』ってここでいうFunctorの外で、ですか?
書き方がまずかったですね。
どこかというのは、 あくまで、クラスの中での話です。
確保するサイズを保持しておいて
関数ポインタが初めて登録されたときに、内部で確保するか、
外で、確保する関数を呼んでもらうかは まだ決めていません。
>type_info の typeid().nameで 型名の取得できるので、
>そこから、なんとか、型変換に持っていけないかなと考えています。
無理です。それを『コンパイラが』知る手段がありません。
ちょっと何がしないのかが見えてきません。
ここでいうFunctorの中なら、
テンプレートパラメータの T が引数で与えられたポインタのpointeeの型になりますけど。
/s 何がしない 何がしたい
失礼。
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;
}
ほんとだ、まずいね。ごめんなさい。
『ポリモーフィックに使用するクラスのデストラクタはvirtualに』
しとかなきゃあかんですな。
ってことで
virtal ~FuncBase() = 0;
とでも付け加えておいてください。
PAIさま、お世話になっております。
調べてみたのですが、わからなかったので教えていただけませんか?
>virtal ~FuncBase() = 0;
この書き方はうまくいきますか?
いろいろ試してみたのですが、エラーがでてしまって、できませんでした。
virtal ~FuncBase(){};
は大丈夫なのですが・・・・
それと、これを仮想関数にすることによりどのようにかわるのでしょうか?
delete をした時に、きちんと派生クラスのサイズ分解放してくれるのでしょうか?
それとも、
~Functor(){
}
PAIさま、お世話になっております。
調べてみたのですが、わからなかったので教えていただけませんか?
>virtal ~FuncBase() = 0;
この書き方はうまくいきますか?
いろいろ試してみたのですが、エラーがでてしまって、できませんでした。
virtal ~FuncBase(){};
は大丈夫なのですが・・・・
それと、これを仮想関数にすることによりどのようにかわるのでしょうか?
delete をした時に、きちんと派生クラスのサイズ分解放してくれるのでしょうか?
それとも、
~Functor(){
}
の中で何かを書くことで正しく解放できるようになるということなのでしょうか?
>>virtal ~FuncBase() = 0;
>この書き方はうまくいきますか?
FuncBase::~FuncBase() の実体をどこかで作ってあげればいける。
クラス定義内で
>virtal ~FuncBase(){};
でもOK。
>それと、これを仮想関数にすることによりどのようにかわるのでしょうか?
ちゃんと派生先のデストラクタが呼ばれてくれる。
operator delete も派生先が適応されてしっかり派生先のサイズ分開放される。