例えば、関数ポインタを引数に取る関数functionがあるとして、
typedef void (*Callback)( int n );
void Function( Callback cb )
{
cb( 100 );
}
というような。
このFunctionのcbへ、staticではないメンバ関数ポインタ、
例えば以下のHogeのFncメソッド
struct Hoge
{
void Fnc( int n ){ cout << n << end; }
};
を渡すにはどうしたらよいのでしょうか?
typedefや、Functionが変更不可ということで。
Hoge hoge;
Function( ????? );
------
(vc6)
#include <iostream>
struct Hoge
{
void Callback( int n )
{
std::cout << n << std::endl;
}
};
typedef void ( Hoge::*CALLBACK )( int );
void Test( CALLBACK func, Hoge *pHoge, int n )
{
( pHoge->*func )( n );
}
int main()
{
Hoge hoge;
Test( &Hoge::Callback, &hoge, 10 );
return 0;
}
こんな感じで。
Hoge のインスタンスを渡してやらないと呼べません。
int main()
{
Test( &CTest::Callback, &test, 10 );
return 0;
}
なんか下にごみが残ったね。
2つ目の main は無視してください。
関数名変だけど気にしないでね…
もうここまで来たら一人で書きまくってるの気にしないでどんどんいこー。
> typedefや、Functionが変更不可ということで。
void Fnc( int n ) と void Hoge::Fnc( int n ) は全然別物なので、typedef を変えな
いのは無理です。
Hoge のインスタンスが必要なので、Function を変えないのも無理です。
以下、関数名等を tiha さんのに極力合わせたサンプル。
#include <iostream>
struct Hoge
{
void Fnc( int n )
{
std::cout << n << std::endl;
}
};
typedef void ( Hoge::*CALLBACK )( int );
void Function( CALLBACK cb, Hoge &hoge, int n )
{
( hoge.*cb )( n );
}
int main()
{
Hoge hoge;
Function( &Hoge::Fnc, hoge, 100 );
return 0;
}
> typedefや、Functionが変更不可ということで。
Hoge::Fncは変えるな、と言及されてなかったので…
こんなのでどお?
#include <iostream>
typedef void ( *Callback )( int n );
void Function( Callback cb )
{
cb( 100 );
}
void Fnc( int n )
{
std::cout << n << std::endl;
}
struct Hoge
{
Hoge():Fnc(::Fnc){}; //コンストラクタで関数ポインタ渡し
Callback Fnc;
};
int main( int,char** )
{
Hoge hoge;
Function( hoge.Fnc );
return 0;
}
struct からの関数ポインタ渡しだったので咄嗟にこっちがでてきた。
BCCでは通りましたが・・・反則ですか?
>void Fnc( int n ) と void Hoge::Fnc( int n ) は全然別物なので、
>typedef を変えないのは無理です。
>Hoge のインスタンスが必要なので、Function を変えないのも無理です。
無理ですか・・。それがわかっただけでもよかったです。
ありがとうございました。
static変数使う方法を一つみつけました。
#include <iostream>
struct Hoge
{
static void* m_p;
void Fnc( int n )
{
std::cout << n << std::endl;
}
static Callback( n );
{
Hoge* phoge = (Hoge*)m_p;
phoge->Fnc( n );
}
};
void* Hoge::m_p;
typedef void ( *CALLBACK )( int );
void Function( CALLBACK cb )
{
cb( 100 );
}
int main()
{
Hoge hoge;
Hoge::m_p = &hoge;
Function( &Hoge::Fnc );
return 0;
}
て、ちと無理あるか・・
エラー出ますよ(VC++.NET 2003)。
やっぱり、
void Func( int )
を取る関数に
void Hoge::Func( int )
は渡せません。
↑のは、tiha さん@21:03:38 へのレスです。
で、鷲尾不徳 さん
それって、
#include <iostream>
typedef void ( *Callback )( int n );
void Function( Callback cb )
{
cb( 100 );
}
void Fnc( int n )
{
std::cout << n << std::endl;
}
int main( int,char** )
{
Function( Fnc );
return 0;
}
と同じじゃん。
呼び出す対象の Fnc が Hoge のメンバじゃないですもん。
あ、すいません。
> Function( &Hoge::Fnc );
は、
Function( &Hoge::Callback );
の間違いでした。
>と同じじゃん。
>呼び出す対象の Fnc が Hoge のメンバじゃないですもん。
自分のじゃ、見た目それっぽく動くようにごまかしただけですね…
そこまで言うならお目にかけよう、禁断の魔技!
…まともに動きゃしねぇがな。
よい子は真似しちゃいけないよっ☆
#include <iostream>
#include <cstdio>
struct Hoge
{
void Fnc( int n )
{
std::cout << n << std::endl;
}
};
typedef void ( *CALLBACK )( int );
void Function( CALLBACK cb, int n )
{
( *cb )( n );
}
int main()
{
char s[ 80 ];
std::memset( s, 0, 80 );
std::sprintf( s, %p, ( &Hoge::Fnc ) );
long lPtr = std::strtol( s, NULL, 16 );
CALLBACK pFunc = reinterpret_cast< CALLBACK >( lPtr );
Function( pFunc, 100 );
return 0;
}
>tiha さん
Hoge に static な Callback を追加するのと、
Fnc 自体を static にするのはさほど変わらないような…
「Function と typedef を変更しない」にこだわるあまり
「コールバック関数のアドレスとして static でないものを渡す」が軽視されてます。
禁断の魔技の sprintf / strtol がやってることを自力でやってみる。
使い物にならないことに変わりはない。
#include <iostream>
#include <cstdarg>
struct Hoge
{
void Fnc( int n )
{
std::cout << n << std::endl;
}
};
typedef void ( *CALLBACK )( int );
void Function( CALLBACK cb )
{
( *cb )( 100 );
}
void Test( int dummy, ... )
{
va_list ap;
va_start( ap, dummy );
CALLBACK pFunc = va_arg( ap, CALLBACK );
Function( pFunc );
va_end( ap );
}
int main()
{
Test( 0, &Hoge::Fnc );
return 0;
}
真っ当な方法ではどうやっても無理だと思います。
俺の禁断の魔技みたいな、真っ当じゃない方法でも可能性を模索しますか?
そうなるともはや、インラインアセンブラとか使わざるを得ない気がしますが。
俺はそっちはわかんないので、どなたか「やってみよう」と思う方がいらっしゃいまし
たらお願いします。