3つの異なるデータ型を格納できるベクトルをC++で作成しようとしています。 boostライブラリを使いたくありません。何かのようなもの:
vector<type1, type2, type3> vectorName;
テンプレートを作成する必要がありますか?そして、もしそうなら、私はそれをどのように行いますか?
複数の型を同じベクターに格納する最も簡単な方法は、それらを親クラスのサブタイプにして、目的の型がクラスでない場合はクラスにラップすることです。
class Parent
{
//anything common to the types should be declared here, for instance:
void print() //make this virtual if you want subclasses to override it
{
std::cout << "Printing!";
}
virtual ~Parent(); //virtual destructor to ensure our subclasses are correctly deallocated
};
class Type1 : public Parent
{
void type1method();
};
class Type2 : public Parent
{
void type2Method();
};
class Type3 : public Parent
{
void type3Method();
};
次に、子タイプへのポインターを格納できるParent
ポインターのベクトルを作成できます。
std::vector<Parent*> vec;
vec.Push_back(new Type1);
vec.Push_back(new Type2);
vec.Push_back(new Type3);
ベクトルから要素に直接アクセスする場合、Parent
に属するメンバーのみを使用できます。たとえば、次のように記述できます。
vec[0]->print();
だがしかし:
vec[0]->type1Method();
エレメントタイプはParent*
として宣言されており、Parent
タイプにはtype1Method
がありません。
サブタイプ固有のメンバーにアクセスする必要がある場合、次のようにParent
ポインターをサブタイプポインターに変換できます。
Parent *p = vec[0];
Type1 *t1 = nullptr;
Type2 *t2 = nullptr;
Type3 *t3 = nullptr;
if (t1 = dynamic_cast<Type1*>(p))
{
t1->type1Method();
}
else if (t2 = dynamic_cast<Type2*>(p))
{
t2->type2Method();
}
else if (t3 = dynamic_cast<Type3*>(p))
{
t3->type3Method();
}
この種の明示的な型分岐を避け、代わりに仮想メソッドに依存することは、一般的にはより良い考えと考えられていますが。
上記の例で行ったように、動的割り当てを使用する場合は、ポインターをベクターから削除する前に必ず削除してください。または、スマートポインタ(おそらくstd::unique_ptr
)を使用して、メモリが自動的に処理するようにします。
std::vector<std::unique_ptr<Parent>> vec;
3つの異なるデータ型を格納できるベクトルをC++で作成しようとしています。
ここでの答えは、実際には特定のユースケースによって異なります。
オブジェクトが何らかの方法で接続され、類似している場合-基本クラスを作成し、そこからすべてのクラスを派生させて、ベクトルストアunique_ptr
sを親クラスに作成します(ApproachingDarknessFishの回答を参照)詳細については)、
オブジェクトがすべて基本的な(組み込み)タイプである場合-タイプをグループ化し、vector<yourUnionType>
を定義するunion
を使用します。
オブジェクトのタイプが不明であるが、それらが同様のインターフェースを共有し、基本クラスを作成して、テンプレート化された子クラスを派生させる場合(template <typename T> class container: public parent{};
)、次のようにvector<unique_ptr<parent>>
を作成する場合最初のケース、
オブジェクトが何らかの理由で接続できないタイプである場合(たとえば、vector
はint
、std::string
、およびyourType
を格納します)、それらを経由して接続します2のようなunion
または-さらに良い...
...時間があり、何かを学びたい場合は、boost::any
の実装方法を確認し、ライブラリ自体を使用したくない場合は、自分で実装してみてください。見た目ほど難しくはありません。
std :: anyを使用し、オブジェクトをベクトルとしてanyとして保存し、それらを取り出すときにtype()== typeid(mytype)を使用することができます
https://en.cppreference.com/w/cpp/utility/any
ただし、これはC++ 17以降のみです。
ベクトルである必要がありますか?ジェネリック型のリンクリストを検討し、そのリストを反復処理し、typeid()を使用してノードのデータ型を把握し、node.get()関数でデータをプルすることができます。