0

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

我的问题是要知道要存储的对象的大小,因为它可以是给定基类的任何派生类。我不能只为基类的对象分配内存,对,因为它更小。我想,typeof运算符也只会给出基类的大小,对吧?

这是我的示例代码。请参阅评论以了解我的意思。请原谅我的原创性......</p>

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 的生命周期内保留属性对象

谢谢!

4

2 回答 2

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); }
};
于 2010-11-28T21:56:53.673 回答
2

我看到了两种可能性。

  • 给出BaseA一个纯虚成员函数,可能称为clone,负责生成调用它的实例的副本。那么可能的构造函数就BaseB变成了

    BaseB (BaseA const &instanceAX) { instanceA = instanceAX.clone (); }

  • 您也可以避免传递原始指针并boost::shared_ptr改为使用。这样,由于它是引用计数的,因此您的调用者不会导致BaseA用于构造的派生的过早破坏BaseB。您必须调整BaseA * instanceA;以阅读boost::shared_ptr <BaseA> instanceA;ThenBaseB的构造函数可能如下所示:

    BaseB (boost::shared_ptr <BaseA> a) : instanceA (a) { }

第一种方法的问题是,一些继承自的客户端程序员DerivedA1可能会忘记clone在他的派生中实现。第二种方法的主要问题是要求每个用户BaseB在堆上分配属性对象(因为BaseB无论如何您都在 s 构造函数中进行复制,但至少总内存消耗不会增加)

于 2010-11-28T22:00:10.203 回答