3

スタック割り当てオブジェクトを使用してオブジェクトを異種ベクトルに格納する

こんにちは、

CA1、CA2、およびおそらくその他に派生した抽象クラス CA があるとします。

これらの派生型のオブジェクトを、クラス CB に埋め込んだベクトルに入れたいと考えています。ポリモーフィズムを正しく行うには、ポインターのベクトルを格納する必要があります。

class CB
{
    std::vector <CA*> v;
};

ここで、次の主な機能があるとします。

int main()
{
    CB b;
    CA1 a1;
    CA2 a2;
    b.Store( a1 );
    b.Store( a2 );
}

元のオブジェクトが破棄されたときに格納されたオブジェクトが存続するように、メソッドを簡単な方法で記述するにはどうすればよいですかvoid CB::Store(const CA&)(上記の単純な例では発生しません)。

私の問題は、オブジェクトのアドレスをベクターにコピーする前に、まずオブジェクトをヒープにコピーする必要があることですが、派生型のオブジェクトを作成するにはどうすればよいですか? 確かに、RTTI を使用して、考えられるすべての型を検索し、ポインターを作成して割り当て、割り当てられた空間に (適切なキャストを使用して) オブジェクトをコピーしてから、ベクターにプッシュすることができます。しかし、これは非常に複雑に思えますね。

もっと簡単な方法はありますか?

(そして、メインで動的割り当てを使用せずに!)

4

3 に答える 3

7

通常、クローン機能を提供します。

struct CA
{
    virtual CA *clone(void) const = 0;
    virtual ~CA() {} // And so on for base classes.
}

struct CA1 : public CA
{
    virtual CA *clone(void) const
    {
        return new CA1(*this);
    }
}

struct CA2 : public CA
{
    virtual CA *clone(void) const
    {
        return new CA2(*this);
    }
}

これは仮想コンストラクターと呼ばれ、実行時にオブジェクトのコピーを作成できます。

void CB::Store(const CA& pObject)
{
    CA *cloned = pObject.clone();
}

Boost.Pointer Containerライブラリの使用を検討する必要があります。あなたのコードは次のようになります。

boost::ptr_vector<CA> objects;

void CB::Store(const CA& pObject)
{
    objects.push_back(pObject->clone());
}

これで、自分でメモリを管理する必要がなくなりました。ライブラリはクローン関数も尊重し、オブジェクトのコピーを作成するときにそれを呼び出します。チュートリアルはこちら

于 2009-10-21T13:53:09.320 に答える
2

派生クラスが実装する抽象クラスに clone() 関数が必要なようです。

class CA
{
   public:
   virtual ~CA() {}
   virtual CA* clone() const = 0;
}

class CA1 : public CA
{ 
    public:
    virtual CA *clone() const
    {
       return new CA1(*this);
    }
};
于 2009-10-21T13:51:26.013 に答える
1

可能性は、その引数の型で Store をテンプレート化することです:

class CB
{
public:
    template<class T>
    void Store(const T& t)
    {
         v.push_back(new T(t));
    }

private:
    std::vector <CA*> v;
};

ただし、警告: 他の人が投稿した "clone()" ソリューションとは異なり、これはスライスしやすい傾向があります。たとえば、これは正常に機能します。

CB b;
CA1 a1;
CA2 a2;
b.Store(a1);
b.Store(a2);

しかし、これはしません:

CA1 a1;
CA* a = &a1;
b.Store(*a); //Ouch! this creates a new CA, not a CA1

保護されたコピー クターを CA に与えることで、このような悪用を防ぐことができます。ただし、CA1 をさらにサブクラス化すると、問題が再発します。

于 2009-10-21T15:36:58.567 に答える