6

検索してみましたが、何も返されません(私は思います)。

抽象クラスのベクトルを作成することは可能ですか?

たとえば、スーパークラスのユニットがあります。

サブクラスには、兵士、車両、爆撃機があります。

ただし、1 つのベクトルに任意のサブクラスのインスタンスが必要です。たとえば、ベクトル UnitList は兵士と車両の両方のインスタンスを保持できますか?

これは可能ですか?役立つ場合は、C++を使用しています。

4

4 に答える 4

11

はい。ただし、ポインターまたはスマート ポインターのいずれかを使用する必要があります (私はこれを使用します)。

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>ます。これは次の理由で違法です。

  1. ベクトルをいくつかの要素で初期化する場合、割り当ては失敗します。ベクトルはオブジェクトを連続メモリに内部的に格納します。オブジェクトを作成する必要があることを意味するため、事前割り当ては失敗しますが、これは抽象クラスでは実行できません。

  2. できたとしても、または基本クラスが抽象的ではなかったとしても、オブジェクトのスライスに悩まされるため、あまり役に立ちません。

于 2012-04-26T17:39:35.010 に答える
9

これらのオブジェクトはそれぞれサイズが異なるため、これを行う適切な方法は、基本クラスへのポインターを含むコンテナーです(そして、デストラクタ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()));
于 2012-04-26T17:53:04.653 に答える
2

ベクトル テンプレートは、コンパイル時にその要素のサイズをコンパイラに伝えることができる必要があるため、抽象クラスのオブジェクトのベクトルを文字通り作成することはできません。ただし、オブジェクトのベクトルではなく、オブジェクトへのポインターのベクトルを保持することで、必要なものを取得できます。

更新: 抽象クラス自体には既知のサイズがあります。実際には、コンパイル時にサイズが不明な最も派生した型のインスタンスです。(これを指摘してくれた@LuchianGrigoreと@MooingDuckに感謝します。)

于 2012-04-26T17:43:28.773 に答える
1

これを行うことは不可能だと思います:

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));

私はそれをテストしていませんが、とにかく私の頭の中では理にかなっています。

于 2012-04-26T17:44:42.833 に答える