1
void f(string str,int i )
{
  cout<<str.c_str()<<endl;
  cout<<i<<endl;
}

typedef void (*PF)(int i,string str);


int _tmain(int argc, _TCHAR* argv[])
{

   PF pf=(PF)(void*)&f;

   pf(10,string()); //runtime-error

   return 0;

}

必要に応じて、データ型が消去されfたアドレスを使用して関数を呼び出す必要があります (上記のコードなど)。fただし、このソリューションでは、コンパイル中にデータ型をチェックできないため、安全でない関数呼び出しが発生する可能性があります。パラメータの型が引数と異なる場合にコンパイラにエラーを報告させる方法はありますか?

このようなもの:</p>

void f(T1 i,T2 j)
{
  T1 p* = new i.real_type; //if i.real_type is different from T1, it will lead a compiling 
....
}

とても感謝しています。

4

4 に答える 4

1

C++ で使用できる実行時の型情報はtypeiddynamic_castのみであり、これらは多相型 (仮想関数を持つクラス型) でのみ機能します。関数ポインターは、必要な情報を格納しません。

本当に、関数ポインタのキャストは避けるべきです。関数ポインターのケースが必要な唯一の場所は、GetProcAddressまたはからの戻り値dlsymです。

于 2012-07-20T18:43:06.467 に答える
0

パラメータのタイプが引数と異なる場合に、コンパイラにエラーを報告させる方法はありますか?

どうやって知ることができますか?あなたは型システムを破壊しました(それがsにキャストすることvoid*です)。C ++コンパイラに、関数ポインタが何かへのポインタであるかのように見せかけ、次に、この何かへのポインタが別の種類の関数へのポインタであるように見せかけるように指示しました。

コンパイラには、元の型が何であるかを知る方法がありません。それが知っているのは、があるということvoid*だけです、そしてあなたはそれを何かに変換するように頼みました。まったく機能させるためにvoid*、C ++言語では、コンパイラーがどこvoid*から来たのか、そしてそれが何であったのかを魔法のように知る必要はありません。したがって、何にでもキャストできますが、仕様では、キャスト先が元のタイプでない場合、未定義の動作が発生することが規定されています。

C ++の型システムは、コンパイラが何か間違ったことをしたことを検出できるようにするものです。それを破壊し、その後それを間違って行うことによって、あなたは合理的な宇宙に住むすべての権利を放棄しました。あなたはコンパイラーに「私は自分が何をしているのか知っている」と言ってから、自分の足を撃ちました。

最善の方法は、 Boost.Anyを使用して関数ポインターを格納することです。元々保存されていたもの以外にキャストしようとすると、例外がスローされます。もちろん、実行時に。

于 2012-07-20T19:02:07.237 に答える
0

さまざまな関数の種類に応じて、テストまたはデバッグ ビルド用に何かを追加します。

// Once off init call
DEBUG_INSERT (&f, INT_STRING);

...

DEBUG_CHECK_FUNC (pf, INT_STRING); 
pf(10,string()); //runtime-error

いくつかのブーストおよび/またはc ++ 11マジックを使用すると、「KIND」を持つ必要がなくなり、元の関数型から暗黙的に推測できると確信しています。おそらく、次のような呼び出しになる可能性があります。

CHECKED_CALL (pf, 10, string ());

リリース ビルドでは引数を指定して関数を呼び出すだけで、デバッグ ビルドではチェックも行われます。

于 2012-07-20T19:20:34.653 に答える
0

いいえ。void* から「型を取得」する安全な方法はありません。void* が不要になるように、実際の問題を解決するクリーンな方法がある可能性があります。そこに新しい質問を投稿して、特定のタスクを説明することをお勧めします。

于 2012-07-20T18:49:54.010 に答える