如何为对象分配内存我不知道真正的类型? C ++

时间:2010-11-28 21:50:39

标签: c++ pointers memory-management contains derived-class

我想将某个派生类的对象存储为另一个对象的属性。

我的问题是要知道要存储的对象的大小,因为它可以是给定基类的任何派生类。我不能只为基类'对象分配内存,因为它更小。我想, 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 的生命周期中的属性对象。

谢谢!

2 个答案:

答案 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的构造函数中复制,至少总内存消耗但是不会上升。