【问题标题】:Storing heterogeneous objects in vector with stack-allocated objects使用堆栈分配的对象将异构对象存储在向量中
【发布时间】:2010-12-08 17:26:37
【问题描述】:

使用堆栈分配的对象将对象存储在异构向量中

你好,

假设我有一个抽象类 CA,派生到 CA1、CA2 或其他类。

我想将这些派生类型的对象放入一个向量中,并将其嵌入到一个类 CB 中。为了获得正确的多态性,我需要存储一个指针向量:

class CB
{
    std::vector <CA*> v;
};

现在,假设我有以下主要功能:

int main()
{
    CB b;
    CA1 a1;
    CA2 a2;
    b.Store( a1 );
    b.Store( a2 );
}

我如何以简单的方式编写方法void CB::Store(const CA&amp;),以便在原始对象被销毁时存储的对象仍然存在(在上面的简单示例中不会发生)。

我的问题是我需要先在堆上复制对象,然后再将它们的地址复制到向量中,但是如何创建派生类型的对象?当然,我可以使用 RTTI,搜索所有可能的类型,创建和分配指针,然后将对象复制(通过适当的转换)到分配的空间中,然后再将其推入向量中。但这似乎很复杂,不是吗?

有没有更简单的方法?

(并且没有在 main 中使用动态分配!)

【问题讨论】:

  • 主要,他说。我认为他想尽量让艰苦的工作(动态分配)完成并远离客户。

标签: c++ inheritance vector polymorphism dynamic-memory-allocation


【解决方案1】:

通常,你会提供一个克隆功能:

struct CA
{
    virtual CA *clone(void) const = 0;
    virtual ~CA() {} // And so on for base classes.
}

struct CA1 : public CA
{
    virtual CA *clone(void) const
    {
        return new CA1(*this);
    }
}

struct CA2 : public CA
{
    virtual CA *clone(void) const
    {
        return new CA2(*this);
    }
}

这叫做virtual constructor,你可以在运行时构造对象的副本:

void CB::Store(const CA& pObject)
{
    CA *cloned = pObject.clone();
}

您应该考虑使用Boost.Pointer Container 库。你的代码是:

boost::ptr_vector<CA> objects;

void CB::Store(const CA& pObject)
{
    objects.push_back(pObject->clone());
}

现在您无需自己管理内存。该库还尊重克隆函数,并在复制对象时调用它。 Tutorial here.

【讨论】:

  • 我想你错过了CA、CA1和CA2之间的继承关系
  • 虚拟析构函数在哪里?
  • 哎呀,哈哈。遗产对我来说是愚蠢的。我故意留下诸如虚拟析构函数之类的细节,因为它妨碍了答案。
  • 非常好的解决方案,谢谢,我今天学到了一些东西!我会查看 Boost 指针库。
【解决方案2】:

听起来您需要在派生类将实现的抽象类中的 clone() 函数。

class CA
{
   public:
   virtual ~CA() {}
   virtual CA* clone() const = 0;
}

class CA1 : public CA
{ 
    public:
    virtual CA *clone() const
    {
       return new CA1(*this);
    }
};

【讨论】:

  • 我认为你错过了 CA 和 CA1 之间的继承关系
  • ...以及一个虚拟析构函数和一个“public:”;-)
【解决方案3】:

一种可能性是根据其参数的类型对 Store 进行模板化:

class CB
{
public:
    template<class T>
    void Store(const T& t)
    {
         v.push_back(new T(t));
    }

private:
    std::vector <CA*> v;
};

一个警告:与其他人发布的“clone()”解决方案不同,这很容易被切片。例如,这很好用:

CB b;
CA1 a1;
CA2 a2;
b.Store(a1);
b.Store(a2);

但这不是:

CA1 a1;
CA* a = &a1;
b.Store(*a); //Ouch! this creates a new CA, not a CA1

向 CA 提供受保护的复制 ctor 可防止此类滥用。但是,如果我们进一步继承 CA1,问题又回来了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-30
    • 1970-01-01
    • 2015-03-13
    • 2020-12-19
    • 2018-04-02
    • 2017-11-08
    • 2013-01-25
    • 2021-01-19
    相关资源
    最近更新 更多