如何在基类向量中返回派生对象的副本?

时间:2013-01-17 16:00:24

标签: c++ abstract-class copy-constructor derived-class

这是问题,我有一个指向抽象基类的指针向量,这些抽象基类填充了派生对象,如下所示:

class AbstractBase { /* ... */ };  

clase Derived1 : public AbstractBase {
    Derived1() { }
    Derived1( const AbstractBase& abc ) { /* ... */ }
};

/* ... */

vector< AbstratcBase* > lThingies;

const AbstractBase& getThingie(int pos) {
    return *lThingies[pos];
}

为了获取元素的副本,我使用派生类“copy constructor”,如下所示:

Derived1 d1 = getThingie(2);

但问题是我不喜欢这样:在构建类“derived42”时没有办法强制执行这个“复制构造函数”,即使你记得它很容易弄错(就像让它成为递归电话一样,发生在我身上)。

我的问题是: 有更好的方法吗?怎么样?

更新
我正在寻找的解决方案的一个“未写”要求是将派生的对象的副本作为局部变量,所以我不要忘记删除

更多信息:
有许多 lThingies ,在运行时,我可以知道(derived1,derived2等)中包含的派生对象是什么,但在编译时却不知道。

3 个答案:

答案 0 :(得分:4)

您可以在clone中创建纯虚拟AbstractBase函数,该函数返回AbstractBase指针,并在派生类中覆盖clone

<小时/> 严格意见:

虽然(在我看来)这是一种粗略和过时的做法。我建议重新设计,以便首先消除这样做的必要性。

详细阐述我对虚拟构造函数的“粗略和过时”的看法(我确信这会引起争议):

  • 实际上是健壮的/通用克隆需要模仿分配器,就像一些STL结构一样。但是,它不可能。
  • 您何时想要复制一个您不知道具体类型的对象?我质疑该用例的合法性。

答案 1 :(得分:0)

您知道getThingie返回Derived1吗?如果你知道这一点,可能你应该将Derived1的返回类型和std::vector中的存储空间更改为Derived1而不是AbstractBase

假设上面的方法不起作用,你可以做一个Derived1 bob = dynamic_cast<Derived1&>(getThingie(...));,它运行时检查thingy是Derived1或更多的派生实例,如果是,它会进行转换 - 如果没有,它会引发异常。

如果您不想打扰运行时检查,因为您确定它是Derived1,只需使用Derived1 bob = static_cast<Derived1&>(getThingy(...));

但是,使用具有继承层次结构的类的实际实例是非常值得怀疑的。有许多事情可能出错。

答案 2 :(得分:0)

class A
{
   public:
   virtual void toto() { std::cout << "Love Java" <<std::endl; }
   virtual A&& Duplicate() { return std::move(A()); }
};

class B : public A
{
   public:
   virtual void toto() { std::cout << "Love C++11" <<std::endl; }
   virtual B&& Duplicate() { return std::move(B()); }
};

int main()
{
   A *a = new B();;

   A&& b(a->Duplicate());

   a->toto();
   b.toto();
}

在主要内容中,您在堆栈上创建B而不知道其类型。 (在c ++ 11中使用rvalue引用)