1

value何かを指すことができるフィールドを持つ C++ クラスを実装しようとしています (boost::any のように)。現在、私は次のことを行っています。

class MyClass {
  void* value;
  template<typename T>
  Myclass(const &T v) {
    value = (void*)(new T(v));
  }
};

問題は、正しい型で内部値のコピーを作成する getValue() 操作を実装することです。

template<typename T>
T getValue() {
 return *value;
}

void* ポインターを参照解除しようとしているため、ここでは機能しません。どのキャスト (static_cast? dynamic_cast? other...) *value が T オブジェクトに適切に変換され、値が元々この型でない場合に例外がスローされるように使用する必要があるのか​​ 疑問に思っていましたか?

ありがとう

4

3 に答える 3

4

a を逆参照することはできませんvoid*。単に意味がありません。クラス自体をジェネリックにしないのはなぜですか? 次に、次のことができます。

template<typename T>
class MyClass {
  T* value;

  MyClass(const T& v) {
    value = new T(v);
  }

  T getValue() {
    return *value;
  }
};

割り当てを解除するデストラクタを作成し、The Rule of Threevalueに従うようにしてください。コピーが不要な場合はコピーを避けるために、 (への参照) を返すのバージョンを作成することもできます。getValueconst T&constT

于 2012-08-10T20:13:52.000 に答える
1

which cast (static_cast? dynamic_cast? other...) *value が T オブジェクトに適切に変換されるように使用する必要があります

この変換を行う必要がある場合はstatic_cast、 を使用する必要があります。これは、一般に (とりわけ) 標準変換を逆にするように設計されています。任意のオブジェクト ポインター型から への標準的な変換がありvoid*、ゲッターはそれを逆にするため、そのために設計されたキャストを使用します。

return *static_cast<T*>(value);

また、コンストラクターから C スタイルのキャストを削除するか、それを a に置き換える必要もありstatic_castます。

Areinterpret_castも機能しますが、「やり過ぎ」です。一般に、必要な変換を実行しながら、できるだけ制限的なキャストを使用する必要があります。

値が元々この型でなかった場合、例外がスローされます

あなたは運が悪いです.C++は、ポインタをにキャストすると、オブジェクトの元の型が何であったかを一般的に知ることができませんvoid*getValueあなたのコードは、呼び出し元が正しい型で呼び出すことに依存しています。たとえば、元の型がcharC++ では 1 バイトであり、コンパイラがgetValue.

dynamic_castはいくつかの限られた状況で型をチェックしますが、テンプレートは完全にジェネリックであるため、それらの限られた状況には当てはまらない場合があります。

これが気に入らない場合は、クラスを変更して、オブジェクト ポインターに加えて、オブジェクトへのポインター(演算子type_infoの使用の結果) を格納することができます。typeid標準ヘッダーを参照してください<typeinfo>。次に、コンストラクターtype_infoの型のオブジェクトを の型のオブジェクトと比較し、一致しない場合はスローします。Ttype_infoTgetValue

あなたが言うように、あなたのクラスは少し似ていることを意図しており、boost::anygetValueていany_castます。そのクラスのソースとドキュメントを参照して、必要なことを行うために必要なトリックを確認できます。それを行う簡単な方法があればboost::any、簡単なクラスになります!

于 2012-08-11T00:48:48.023 に答える
0

できません。C++ はそのようなメカニズムを提供していません。少なくとも直接的には提供していませんvoid*。Aには、コンピューターがそれが何であるかを判断するために必要void*情報がありません。そのための特定のフラグがないため、それが有効なものであるかどうかを「チェック」しようとすることは不可能です。

ただし、オプションがあります。1 つ目は、Java のオブジェクトに似たある種のユニバーサル基本クラスを使用し、そこから他のすべてのクラスを派生させることです。dynamic_cast希望どおりに機能するようになりました(NULLオブジェクトがキャスト先のクラスの有効なオブジェクトでない場合に返されます)。

もう 1 つは、それが自分自身であるオブジェクトのタイプを単純に追跡することです。つまりvoid*、キャストする必要があるものを示す別の値で を拡張することを意味します。

しかし、実際には、どちらも良いアイデアとは思えません。これらを使用するのではなく、変更する必要があるデザインの他の側面がほぼ間違いなくあると思います。テンプレートを @EdS として使用します。たとえば、非常に良いオプションです。

于 2012-08-10T20:14:52.560 に答える