6

Array1 つのオブジェクトに複数のタイプのデータを保持できるベクトルのように、任意のタイプのオブジェクトを保持できる単純なクラスを設計しています。(これは学習用です。)

と呼ばれる空の基本クラスがありますContainer

class Container {};

と呼ばれるテンプレート化されたサブクラスObject:

template <class T>
class Object : public Container {
    T& object;
public:
    Object(T& obj = nullptr) : object(obj) {}
};

s を保持するために使用する sへのポインターの a を保持するArrayクラスがあります。vectorContainerObject

class Array {
    std::vector<Container *> vec;
public:
    template <class T>
    void add_element(const T&);
    auto get_element(int);
};

add_element要素をObjects に格納し、それらをvec:

template <class T>
void Array::add_element(const T& element)
{
    vec.push_back(new Object<T>(element));
}

get_element要素を削除Objectし、呼び出し元に戻します。ここに私の問題があります。から要素を削除するには、その要素のObjectタイプを知る必要がありObjectます。

auto Array::get_element(int i)
{
    return (Object</* ??? */> *)vec[i])->object;
}

保存しているオブジェクトの種類を確認する方法はありますか?

編集:人々はこれは不可能だと主張しているので、これはどうですか. クラス内に型情報を実際に格納する方法はありますか? (Rubyでそれができることは知っています)。それができればget_element、 eachに の戻り値の型を格納できますObject

4

3 に答える 3

2

このテンプレートのラインに沿って、あなたのget_element.

template <class T>
T& Array::get_element(int i, T &t)
{
    Object<T> *o = dynamic_cast<Object<T> *>(vec[i]);
    if (o == 0) throw std::invalid_argument;
    return t = o->object;
}

Array arr;
double f;
int c;

arr.get_element(0, f);
arr.get_element(1, c);

しかし、代わりに、これを使用することもできます:

template <class T>
T& Array::get_element(int i)
{
    Object<T> *o = dynamic_cast<Object<T> *>(vec[i]);
    if (o == 0) throw std::invalid_argument;
    return o->object;
}

f = arr.get_element<double>(0);
c = arr.get_element<int>(1);
于 2012-07-06T22:52:25.673 に答える
1

dynamic_cast <>()をポインターで使用すると、型が一致しない場合にNULLが返されるため、キャストが実際に可能かどうかを確認できます。

ただし、おそらくセットアップを再検討する必要があります。dynamic_castは、回避できる場合は使用したくないものであり、「if object-is-type1 then do this; else if object-is-type2 then do it; else if object-is-type3 ...」は、ほとんどの場合、悪いデザインの確かな兆候です。

get_elementでautoを使用することは、タイプが何であるかわからないという問題を回避するためのトリックである可能性がありますが、それは機能しません。コンパイラはまだ戻り型を知っている必要があります。実行時に変更することはできません。

編集:一歩下がって、「何でも」格納できる配列が本当に必要かどうかを自問することもできます。私は長い間Objective-Cを使用してきましたが、基本的にはすべてが単なる「オブジェクト」であり、人々は何でも何でも呼び出すことができるという考えに基づいて構築されており、すべて実行時に整理されます。ただし、これを実際に使用することはまれであることがわかりました...特にコンテナの場合、使用するすべてのNSArrayには、1つのタイプのオブジェクト、または共通の基本クラスのオブジェクトしかなく、実際には別個の無関係なクラスはありません。 。

于 2012-07-06T22:20:01.673 に答える
1

のような関数の戻り型は、Array::get_elementコンパイル時に決定する必要があります。クラスArrayはコンパイル時にどのタイプのコンテナを格納するかを知らないため、唯一のオプションはベースContainer*ポインタを返すことです。次に、そのコードのユーザーは、仮想関数を使用したりdynamic_cast、それらの一般化されたコンテナーを処理したりできます。

于 2012-07-06T22:19:10.347 に答える