0

基本クラスの Parameter と、2 つの派生クラス (Scalar & Vector) があります。各派生クラスには、関数ポインターを入力として受け取るメンバー関数があります。

Scalar クラスでは:

typedef double (*samplerType)(RandNum& rnState);
void RegisterSampler( samplerType input );

ベクトル クラスでは:

typedef std::vector<double> (*samplerType)(RandNum& rnState);
void RegisterSampler( samplerType input );

さまざまな戻り値の型に注意してください:doublestd::vector<double>. この関数を相互基本クラス Parameter 内で定義したいので、取る関数を変更し(void* input)、Scalar クラスと Vector クラス内で関数を定義するときに次のことを試しました。

samplerType inputSampler = dynamic_cast< samplerType >(input);

ただし、VS 2005 で次のエラーが発生します。

error C2680: 'double (__cdecl *)(RandNum &)' : invalid target type for dynamic_cast
target type must be a pointer or reference to a defined class

Grumble Grumble Grumble... これが C++ で有効かどうか (標準的に許可されている) かどうかはわかりませんが、いずれにせよ、これを私の設計上の欠陥として扱うことになると思います。

したがって、私の標準的なアプローチは、関数の戻り値の型で基本クラスをテンプレート化することですが、できません。基本クラス Parameter は、設計上、すべての型情報を含まないようにする必要があります。 継承を設計する別の方法はありますか?

これをグーグルで試してみたところ、関数ポインタは事実上ゼロになりました。したがって、これは実際には無効な構文であると思いますが、おそらく本当に、本当に珍しい設計上の課題にすぎませんか? これはそれらの場所の別の 1 つであり、救助へのファンクターですか?

4

1 に答える 1

1

James が指摘する設計上の欠陥は別として、関数ポインターから通常のvoid*ポインターにキャストできないことは事実です。ただし、任意の型 (フリーからフリー、メンバーからメンバー) の関数ポインター間でキャストすることはできます。

typedef void (*samplerType)();
// in base class ...
samplerType sampler_;
template<class F>
void RegisterSampler(F sampler){
  // template so the user doesn't have to do the type cast
  sampler_ = reinterpret_cast<samplerType>(sampler);
}
// in derived class, where you access the sampler, you need to cast it back:
// (scalar)
typedef double (*realSamplerType)(RandNum& rnState);
// made-up function ...
void UseSampler(){
  realSamplerType sampler = reinterpret_cast<realSamplerType>(sampler_);
  double ret = sampler(param...);
}
于 2011-04-02T00:29:37.983 に答える