如何为我不知道其真实类型的对象分配内存? C++
我想将某个派生类的对象存储为另一个对象的属性。
对我来说,问题是知道要存储的对象的大小,因为它可以是给定基类的任何派生类。我不能只为基类的对象分配内存,对吧,因为它较小。我想,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 的生命周期内保留属性对象。
谢谢!
I want to store an object of some derived class as a property of another object.
The problem for me is to know the size of the object to be stored, as it can be any derived class of a given base class. I cannot just allocate memory for the base class' object, right, as it's smaller. I suppose, typeof operator would also just give the size of the base class, right?
Here is my sample code. Please, see the comments to understand what I mean. Excuse me for the unoriginality…
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();
}
I could store a pointer instead of the object itself, it would be easier. But I'm not sure I want to rely on the caller to retain the property object for the life of instance instanceB.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
好吧,首先,由于您通过值而不是通过引用或指针传递 BaseA,因此您确实知道类型;这是基地A。 BaseB 被复制到 BaseA 中,并且该 BaseA 副本被发送到该函数。 BaseB 中的任何额外数据都不包含在instanceAX 中。这称为“切片”。
但是,要回答你的问题,你根本不这样做。如果要以这种方式工作,则您的 BaseB 类中需要有一个 clone() 函数。或者,您可以设计一个智能指针或其他可以为您克隆实例的对象。如果您在 comp.lang.c++ 上搜索我的名字以及clone(),您可能会遇到我在那里关于后一个想法的讨论。
Clone函数当然是一个虚函数,它返回当前对象的副本:
Well, first of all, since you pass in your BaseA by value, and not by reference or pointer, you DO know the type; it's BaseA. BaseB was copied into a BaseA and that BaseA copy is sent to the function. Any extra data in BaseB is not contained in instanceAX. This is called "slicing".
But, to answer your question, you simply do not do it this way. You need a clone() function in your BaseB class if it is meant to work this way. Alternatively you might design a smart pointer or other object that can clone the instance for you. If you search for my name on comp.lang.c++ along with clone() you might come across a discussion I had there about this latter idea.
The clone function is of course a virtual function that returns a copy of the current object:
我看到两种可能性。
给
BaseA
一个纯虚拟成员函数,可能称为clone
,它负责生成调用它的实例的副本。那么BaseB
的构造函数可能会变成BaseB (BaseA const &instanceAX) { instanceA = instanceAX.clone (); }
您也可以避免传递原始指针并使用
boost::shared_ptr
代替。这样,由于它是引用计数的,因此您的调用者不会导致用于构造BaseB
的BaseA
派生过早销毁。您必须调整BaseA * instanceA;
才能读取boost::shared_ptr; instanceA;
那么BaseB
的构造函数可能如下所示:BaseB (boost::shared_ptra) : instanceA (a) { }
问题第一种方法的缺点是,某些继承自
DerivedA1
的客户端程序员可能会忘记在其派生中实现clone
。第二种方法的主要问题是要求 BaseB 的每个用户在堆上分配属性对象(因为您无论如何都要在 BaseB 的构造函数中进行复制,不过至少总内存消耗不会增加)I see two possibilities.
Give
BaseA
a purely virtual member function, maybe calledclone
, that is responsible to generate a copy of the instance it is called on. Then the constructor ofBaseB
might becomeBaseB (BaseA const &instanceAX) { instanceA = instanceAX.clone (); }
You could also just avoid passing raw pointers around and use
boost::shared_ptr
instead. This way, since it is reference-counted, your caller can't cause a premature destruction of theBaseA
derivation that was used to constructBaseB
. You'd have to adjustBaseA * instanceA;
to readboost::shared_ptr <BaseA> instanceA;
ThenBaseB
's constructor might look like:BaseB (boost::shared_ptr <BaseA> a) : instanceA (a) { }
The problem of the first aproach is that some client programmer that inherits from, say
DerivedA1
may forget to implementclone
in his derivation. The principal problem of the second aproach would be to require every user ofBaseB
to allocate the property object on the heap (Since you are making a copy insideBaseB
s constructor anyway, at least the total memory consumption would not rise, though)