検索してみましたが、何も返されません(私は思います)。
抽象クラスのベクトルを作成することは可能ですか?
たとえば、スーパークラスのユニットがあります。
サブクラスには、兵士、車両、爆撃機があります。
ただし、1 つのベクトルに任意のサブクラスのインスタンスが必要です。たとえば、ベクトル UnitList は兵士と車両の両方のインスタンスを保持できますか?
これは可能ですか?役立つ場合は、C++を使用しています。
はい。ただし、ポインターまたはスマート ポインターのいずれかを使用する必要があります (私はこれを使用します)。
struct X
{
virtual ~X() {} //<--- as pointed out in the comments
// a virtual destructor is required
// for correct deletion
virtual void foo() = 0;
};
struct Y : X
{
virtual void foo() { }
};
int main()
{
std::vector<X*> a;
a.push_back(new Y);
a[0]->foo();
for ( int i = 0 ; i < a.size() ; i++ )
delete a[i];
return 0;
}
割り当てられたメモリを削除することを忘れないでください。
と仮定しstd::vector<X>
ます。これは次の理由で違法です。
ベクトルをいくつかの要素で初期化する場合、割り当ては失敗します。ベクトルはオブジェクトを連続メモリに内部的に格納します。オブジェクトを作成する必要があることを意味するため、事前割り当ては失敗しますが、これは抽象クラスでは実行できません。
できたとしても、または基本クラスが抽象的ではなかったとしても、オブジェクトのスライスに悩まされるため、あまり役に立ちません。
これらのオブジェクトはそれぞれサイズが異なるため、これを行う適切な方法は、基本クラスへのポインターを含むコンテナーです(そして、デストラクタUnit
があることを確認してください。virtual
オプション1:(boost::ptr_vector
ブーストライブラリが必要ですが、とにかく持っている必要があります)
ptr_vector<Unit> units;
units.push_back(new Soldier());
オプション2: std::vector<std::unique_ptr<Unit>>
(C ++ 11コンパイラが必要)
std::vector<std::unique_ptr<Unit>> units;
units.emplace_back(std::unique_ptr<Unit>(new Soldier()));
ベクトル テンプレートは、コンパイル時にその要素のサイズをコンパイラに伝えることができる必要があるため、抽象クラスのオブジェクトのベクトルを文字通り作成することはできません。ただし、オブジェクトのベクトルではなく、オブジェクトへのポインターのベクトルを保持することで、必要なものを取得できます。
更新: 抽象クラス自体には既知のサイズがあります。実際には、コンパイル時にサイズが不明な最も派生した型のインスタンスです。(これを指摘してくれた@LuchianGrigoreと@MooingDuckに感謝します。)
これを行うことは不可能だと思います:
std::vector<Unit> unit_list;
unit_list.push_back(Soldier(params));
Soldier、Vehicle、および Unit は異なる量のメモリを使用するためです。
ただし、すべてのポインターは一定量のメモリを占有するため、ポインターを使用できる場合があります。
std::vector<Unit*> unit_list;
unit_list.push_back(new Soldier(params));
私はそれをテストしていませんが、とにかく私の頭の中では理にかなっています。