オブジェクトにメモリを割り当てる方法私は本当のタイプのことを知らないのですか? C ++
-
29-09-2019 - |
質問
派生クラスのオブジェクトを別のオブジェクトのプロパティとして保存したいと思います。
私にとっての問題は、特定のベースクラスの派生クラスである可能性があるため、保存するオブジェクトのサイズを知ることです。ベースクラスのオブジェクトにメモリを割り当てることはできません。私は考えます、 typeof また、オペレーターはベースクラスのサイズを与えるだけですよね?
これが私のサンプルコードです。私が何を意味するのかを理解するためのコメントを見てください。不可分のために私をすみません…
BaseA {};
DerivedA1 : BaseA {public: void property() { cout << 1; }};
DerivedA2 : BaseA {public: void property() { cout << 2; }};
// etc. - several derived classes.
BaseB // Contains (or links to) an instance of class derived from BaseA.
{
public:
BaseA * instanceA;
BaseB (BaseA instanceAX)
{
// ??? => How to allocate memory for the object
// I don't know the real type of?
instanceA = new BaseA (instanceAX);
}
BaseB (BaseA instanceAX) { delete instanceA; }
};
main()
{
DerivedA1 instanceA1;
BaseB instanceB (instanceA1);
// Use "property" regardless of which derived class it belongs to.
instanceB.instanceA->property();
}
オブジェクト自体の代わりにポインターを保存できますが、簡単です。しかし、インスタンスの寿命のためにプロパティオブジェクトを保持するために発信者に頼りたいかどうかはわかりません instanceb.
ありがとう!
解決
まあ、まず第一に、あなたは参照やポインターではなく、価値によってあなたのbaseaを渡すので、あなたはタイプを知っています。それはbaseaです。 Basebはbaseaにコピーされ、そのベースアコピーは関数に送信されます。 BaseBの追加データはInstanceAxに含まれていません。これは「スライス」と呼ばれます。
しかし、あなたの質問に答えるために、あなたは単にこのようにそれをしないでください。 BaseBクラスがこの方法で動作することを意図している場合、BaseBクラスでクローン()関数が必要です。または、インスタンスをクローン化できるスマートポインターまたは他のオブジェクトを設計する場合があります。 comp.lang.c ++でclone()で私の名前を検索すると、この後者のアイデアについて私がそこに持っていた議論に出くわすかもしれません。
クローン関数は、もちろん、現在のオブジェクトのコピーを返す仮想関数です。
struct BaseA
{
virtual BaseA* clone() const = 0;
};
struct BaseB : BaseA
{
BaseB* clone() const { return new BaseB(*this); }
};
他のヒント
2つの可能性があります。
与える
BaseA
おそらく呼ばれる純粋に仮想メンバー関数clone
, 、それが呼び出されるインスタンスのコピーを生成する責任があります。次に、のコンストラクターBaseB
になるかもしれませんBaseB (BaseA const &instanceAX) { instanceA = instanceAX.clone (); }
生のポインターを渡すことを避けて使用することもできます
boost::shared_ptr
代わりは。このように、それは参照カウントであるため、あなたの発信者はの早期破壊を引き起こすことはできませんBaseA
構築に使用された派生BaseB
. 。調整する必要がありますBaseA * instanceA;
読むboost::shared_ptr <BaseA> instanceA;
それでBaseB
'のコンストラクターは次のように見えるかもしれません:BaseB (boost::shared_ptr <BaseA> a) : instanceA (a) { }
最初のアプローチの問題は、から継承するクライアントプログラマーの一部が、たとえば DerivedA1
実装を忘れるかもしれません clone
彼の派生で。 2番目のアプローチの主な問題は、すべてのユーザーを要求することです BaseB
ヒープにプロパティオブジェクトを割り当てるには(内部にコピーを作成しているため BaseB
とにかくSコンストラクター、少なくとも総メモリ消費量は増加しません)