2

最近、任意のデータ型 (uint8、unint16、uint32、または unint64) である単一のオブジェクトが必要なプロジェクトに取り組むことにしました (これらは数値のみであり、 +、-、*、/、<<、>>.Boost::variant を調べたのですが、試してみたところ、データを正しく取得できず、落胆しました。そのため、これをエミュレートする他の方法を検討しました。

この点より下は実験であり、間違っているようです。非常に間違っています。

(私はポリモーフィズム/継承についてあまり詳しくないので、事前に申し訳ありません) ベース オブジェクトを作成しようとしましたが、ベース オブジェクトを派生クラス (派生テンプレート クラス) に設定しました。選択したデータ型 (uint8、uint16、uint32、または uint64) です。その後、get() メソッドを使用して以前に設定したデータを簡単に取得できます。

DynamicVariable *a = new TypedDynamicVariable<unsigned int>(12345); 
std::cout << a->get() << std::endl; 
delete a; 

また:

DynamicVariable *a = new TypedDynamicVariable<unsigned char>(255);
std::cout << a->get() << std::endl;
delete a;

表現例:

unsigned int  a = 100;
unsigned char b = 20;
std::cout << a + b << std::endl;

結果: エラー C2039: 'get' : 'DynamicVariable' のメンバーではありません

a->get() が BASE クラスに存在しないというエラーが表示されます。オンラインで検索して、このコード (dynamic_cast) を見つけました。

DynamicVariable *a = new TypedDynamicVariable<int>(12345);
TypedDynamicVariable<int>* p = dynamic_cast<TypedDynamicVariable<int>*>(a);
std::cout << p->get() << std::endl;

ご覧のとおり、これは TypedDynamicVariable* < int > * and dynamic_cast*>(a) (INT であることを指定する) であり、私がやりたいことの目的全体を無効にします。

以下は、私がオンラインで何時間も読んだ不確かな時間から、一種のハッキングしたクラスです。それは私の「解決策」の一般的な概要を持っているようですが、重要なコンテンツが欠落している/改善が必要であること、または実際にはポリモーフィズムが結局私が望むものではない/使用できないことを知っています.

class DynamicVariable
{
    public:
        //constructor & virtual destructor
                 DynamicVariable() {}
        virtual ~DynamicVariable() {}

};

//unique data
template<typename T>
class TypedDynamicVariable : public DynamicVariable
{
    private:
        T _data;

    public:
        //constuctor
        TypedDynamicVariable    (const T& data) : _data(data) { }

        //prototypes
        void    set             (const T& data) { _data = data; }
        T       get             (void)          { return _data; }
};

誰かが上記のクラスの何が問題なのかを理解し、実際の解決策に導くのを手伝ってくれるか、本当に私が探していたものである場合は、boost::variant で正しい方向に向けてください。

ありがとう。

4

3 に答える 3

0

これ

DynamicVariable *a = <some initialisation>
std::cout << a->get() << std::endl; 
delete a; 

a->get()コンパイラは、派生型aが実際に何を指しているかを知らなくても呼び出し方を知っている必要があるため、機能しません。このため、aの宣言された (静的) 型の一部であるメンバーのみが考慮されget、それらの 1 つではありません。
これは、Boost.Variant と Boost.Any が直面するのと同じ問題です。

boost::variant<>最終的に、それは 1 つの単純なことに要約されます: 現在/ boost::any/に格納されている値のタイプがわからない場合、DynamicVariableその値を取得することはできません。
Boost.Variant の場合、 で値を取得しますboost::get<type>(variant)。Boost.Any の場合は、 で値を取得しますboost::any_cast<type>(any)DynamicVariableあなたはおそらく似たようなものを作らなければならないからです。

于 2013-01-22T15:44:48.353 に答える
0

boost::variant特定のタイプがコンパイル時によく知られている場合に使用できます(インスタンス化するにはリストを提供する必要があります)。そのタイプのみをバリアントに格納できます。次に、訪問者を使用して、保存されたデータを簡単に処理できます (which()メンバー関数も参照してください)。

boost::anyまたは、含まれるデータ型に制限なしで使用することもできます。

独自のバリアントを作成することは、従来の OOP の観点から実装することは (ほとんど) 不可能です。異なる戻り値の型 (コンパイル時には不明) を持つメンバーを作成する必要があるためです。get()(これは C++ では不可能です)。

そして、現在のラッパーは(ほとんど)ポリモーフィズムの点で役に立たない-基本クラスへのポインターのコンテナーを持つことができますが、内部に格納されているものを認識できません...したがって、get()知識があればこのストレージから何かを取り出すことはできませんその中に保存されます。これを行うには、いくつかのメソッドを提供する必要があります。RTTI を何らかの形で使用する必要があるため、パフォーマンスの点では完璧とは言えません。boost::variant

于 2013-01-22T15:33:08.903 に答える
0

get()マザー クラスから呼び出すことができるようにするにはDynamicVariable、このメソッドを virtual (この場合は純粋) として定義する必要があります。問題は、get()メソッドDynamicVariableが返す型は何ですか? テンプレートでトリックを見つけようとしないでください。仮想メソッドをテンプレートにすることはできません。

私は、boost::variant や boost::any の大ファンではありません (便利な機能があったとしても!)、設計上の問題を解決するのに簡単すぎる場合があります。

別の方法として、あなたが考えているアプリケーションについて本当に考えます(あなたの例は単純化されていると思います)。次の質問を自問してください: さまざまな型が共通の意味を返しましたか?

  • はいの場合は、返される型の継承も検討する必要があります。メソッドget()はマザー クラスのポインターを返しGeneralReturnType、子の実装は から派生したクラスのポインターを返しますGeneralReturnType
  • いいえの場合は、単にクラスget()から呼び出すべきではありませんDynamicVariable。異なる戻り値の型には共通の意味がないため、考慮get()されるクラスに応じてメソッドの意味が異なります。TypedDynamicVariableしたがって、メソッドを呼び出すには、get()どの派生クラスを持っているかを知っておく必要があります (ポリモーフィズムは、実際には必要なものではないかもしれません...)。
于 2013-01-22T16:20:37.633 に答える