2

タイプがいくつかの制約に依存するメンバーがある場合、どのようにポリモーフィズムを設計しますか。

私がこれを持っているとしましょう:

template<typename T>
class Base
{
public:
  Base() = default;
  virtual ~Base() = default;
  T member;
};

class DerivedA : public Base<int>
{
public:
  DerivedA() {member = 5;}
};

class DerivedB : public Base<float>
{
public:
  DerivedB() = default;
};

さまざまなパラメーターに応じて新しい派生オブジェクトを作成できるようにしたい、つまり:

Base *b;
if (something)
    b = new DerivedA();
else
    b = new DerivedB();

の宣言にテンプレート パラメーターを指定する必要があるため、明らかにこれを行うことはできませんb

これは悪いデザインですか?これをどのように処理しますか?

小さなラッパーを書くことができます:

class Wrapper() {};

template<typename T>
class Base : public Wrapper
{
// ...
};

Wrapper a, b;
a = new DerivedA;
b = new DerivedB;

ただし、またはmemberで宣言された他のメソッドに直接アクセスすることはできません。: をキャストする必要があり、ポリモーフィズムが役に立たなくなります。BaseDerivedreinterpret_cast<DerivedA*>(a)->member

ありがとう

4

2 に答える 2

0

まあ、「アクセス」がテンプレートパラメータに依存している場合T(読み取りなど)、何らかのBase.member方法でそれを提供する必要があります。派生クラスの 1 つにキャストするのも 1 つの方法ですが、. カットオフを回避し、代入性を正しく機能させるには、ポインター/参照の使用を開始する必要があります。reinterpret_cast

Wrapper *a, *b;
a = new DerivedA;
b = new DerivedB;

int a_member = static_cast<DerivedA*>(a)->member;
float b_member = static_cast<DerivedB*>(b)->member;

また、仮想メソッドを追加しWrapperてポリモーフィックにすると、動的キャストも実行できます。

DerivedB* b_derived = dynamic_cast<DerivedB*>(b);
if (b_derived != nullptr) {
    float b_member = b_derived->member;
    // ...
}
于 2012-12-20T13:02:41.740 に答える
0

ラッパーのデザインはまさにあなたが探しているものでなければなりません。問題は、c++ が静的に型指定されているため、型を指定せずにメンバーを宣言できないことです。これを回避する一般的な方法は、必要なすべての機能をサポートする基本クラスを設計し、派生クラスに特定の動作を実装することです。

おそらく問題は、クラスが必要なすべての機能をサポートしていないことです。member を直接使用することは避け、その使用法を仮想メソッドにラップするようにしてください。派生クラスでこれらのメソッドを再実装します。

それでも解決しない場合は、メンバーを抽出する方法を検討してください。おそらく、適切な変換を行う仮想ゲッターとセッターです。

最後の手段として、boost::variant、boost::any を検討してください。しかし、実際には、ラッパーと同様の手法を使用して実装されています。したがって、ラッパーのラッパーを取得します。

于 2012-12-20T12:20:12.813 に答える