我想将某个派生类的对象存储为另一个对象的属性。
我的问题是要知道要存储的对象的大小,因为它可以是给定基类的任何派生类。我不能只为基类'对象分配内存,因为它更小。我想, 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 的生命周期中的属性对象。
谢谢!
答案 0 :(得分:3)
嗯,首先,既然你按价值传递你的BaseA,而不是通过引用或指针,你就知道了类型;这是BaseA。将BaseB复制到BaseA中,并将该BaseA副本发送到该函数。 BaseB中的任何额外数据都不包含在instanceAX中。这称为“切片”。
但是,要回答你的问题,你根本就不这样做。如果要以这种方式工作,您需要在BaseB类中使用clone()函数。或者,您可以设计一个智能指针或其他可以为您克隆实例的对象。如果你在comp.lang.c ++和clone()上搜索我的名字,你可能会遇到关于后一个想法的讨论。
clone函数当然是一个返回当前对象副本的虚函数:
struct BaseA
{
virtual BaseA* clone() const = 0;
};
struct BaseB : BaseA
{
BaseB* clone() const { return new BaseB(*this); }
};
答案 1 :(得分:2)
我看到两种可能性。
给BaseA
一个纯虚拟成员函数,可能称为clone
,它负责生成调用它的实例的副本。然后BaseB
的构造函数可能变为
BaseB (BaseA const &instanceAX) { instanceA = instanceAX.clone (); }
您也可以避免传递原始指针并改为使用boost::shared_ptr
。这样,由于它是引用计数的,因此调用者不会导致过早破坏用于构造BaseA
的{{1}}派生。您必须将BaseB
调整为阅读BaseA * instanceA;
然后boost::shared_ptr <BaseA> instanceA;
的构造函数可能如下所示:
BaseB
第一个方法的问题是一些继承自的客户端程序员,例如BaseB (boost::shared_ptr <BaseA> a) : instanceA (a) { }
可能忘记在他的派生中实现DerivedA1
。第二个方法的主要问题是要求clone
的每个用户在堆上分配属性对象(因为无论如何你在BaseB
的构造函数中复制,至少总内存消耗但是不会上升。