よく分からない。オブジェクトを値で格納しているように聞こえますが、配列はBase
. Derived を割り当てるとすぐに、そのオブジェクトが Base に変換され、オブジェクトの Derived 部分がスライスされるため、これは機能しません。しかし、ベースへのポインターの配列が必要だと思います:
Base * bases[NUM_ITEMS];
for(int i=0; i<NUM_ITEMS; i++) {
int r = get_random_integer();
if(r == 0)
bases[i] = new Derived1;
else if(r == 1)
bases[i] = new Derived2;
// ...
}
ポインターを扱ったことがある場合は、それらを管理し、特にメモリを解放し、オブジェクトのデストラクタを呼び出すためにそれらに対して delete を呼び出す必要があるため、ポインターを失いません。あなたは shared_ptr を使うことができ、あなたのためにそれを管理します:
shared_ptr<Base> bases[NUM_ITEMS];
for(int i=0; i<NUM_ITEMS; i++) {
int r = get_random_integer();
if(r == 0)
bases[i].reset(new Derived1);
else if(r == 1)
bases[i].reset(new Derived2);
// ...
}
bases[x]
これで、別の shared_ptr に渡すことができ、複数の参照があることがわかります。オブジェクトへの最後の参照がスコープ外になると、自動的に削除が呼び出されます。理想的には、生の配列も std::vector に置き換えます。
std::vector< shared_ptr<Base> > bases;
for(int i=0; i<NUM_ITEMS; i++) {
int r = get_random_integer();
if(r == 0)
bases.push_back(shared_ptr<Base>(new Derived1));
else if(r == 1)
bases.push_back(shared_ptr<Base>(new Derived2));
// ...
}
次に、ベクトルを渡し、そのサイズを失わずに、必要に応じてアイテムを動的に追加できます。を使用してベクトルのサイズを取得しbases.size()
ます。shared_ptr
ここについて読んでください。
基本クラスから派生クラスへの変換は、絶対に必要な場合にのみ行う必要があります。通常、 と呼ばれる手法を使用しますpolymorphism
。これは、ベース ポインターで関数を呼び出すことを意味しますが、実際には派生クラスで定義された関数を呼び出し、同じシグネチャ (名前とパラメーターは同じ型) を持ち、override
それに。それについてはウィキペディアの記事を読んでください。本当にキャストする必要がある場合は、生のポインターに対して次のように行うことができます。
Derived1 * d = &dynamic_cast<Derived1&>(*bases[x]);
dynamic_cast を使用すると、間違った型にキャストした場合 (つまり、キャストした型が作成されてベース ポインターに割り当てられた型ではない)、オペレーターによって例外がスローされます。shared_ptr の場合、次の方法もあります。
shared_ptr<Derived1> d = dynamic_pointer_cast<Derived1>(bases[x]);
if(d) {
// conversion successful, it pointed to a derived. d and bases[x] point still
// to the same object, thus share it.
}