2013-01-17 23 views
0

这是问题所在,我有一个指针的向量,以充满派生的对象,像这样一个抽象基类:如何在基类的向量中返回派生对象的副本?

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

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

/* ... */ 

vector< AbstratcBase* > lThingies; 

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

而且得到我使用派生类“的拷贝构造函数”像这样的元素的副本:

Derived1 d1 = getThingie(2); 

但问题是,我不喜欢这样的:有没有办法迫使这个“拷贝构造函数”建设一流“derived42”时的执行情况,即使你还记得它很容易让它出错(比如使它成为递归调用,发生在我身上)。

我的问题是:有没有更好的方法来做到这一点?怎么样?

更新:
其中之一,我正在寻找解决方案的“不成文”的要求是让副本衍生对象作为一个局部变量,所以我不要忘了删除它。

更多信息:
有许多的lThingies和在运行时,我可以告诉大家什么都包含在(derived1,Derived2的,等等)派生的对象,而不是在编译时。

+1

多态性和复制语义不能很好地结合在一起。不要制作显式派生类型的副本。 –

+2

你有没有听说过[virtual constructor idiom](http://www.parashift.com/c++-faq/virtual-ctors.html)? – Fiktik

+0

我听说过虚拟构造函数的习惯用法,但我不想在完成它时删除对象。 – Fabi1816

回答

0

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

假设上述不工作,你可以做一个Derived1 bob = dynamic_cast<Derived1&>(getThingie(...));,它不运行时检查啄是Derived1以上派生的实例,如果它确实是这样投 - 如果不是,它抛出一个例外。

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

但是,处理具有继承层次结构的类的实际实例是非常有问题的。有很多很多事情可能会出错。

+0

你能举出一个可以出错的例子吗? – Fabi1816

+0

@Fabi1816切片就是一个例子。 – Yakk

+0

即使存在潜在的问题,这也解决了我迄今为止的所有问题 – Fabi1816

4

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


严格意见:

这有点粗暴和过时的做法。虽然(在我看来)。我建议重新设计,以免首先做到这一点。

为了详细说明虚拟构造函数用法的我的毛和过时的意见(我敢肯定,这将是有争议的):

  • 要真正健壮/通用克隆将需要模板为分配器,就像一些STL构造一样。但是,它不可能。
  • 你什么时候想要复制一个你不知道具体类型的对象?我质疑该用例的合法性。
+1

有意详细说明“粗糙和过时”的位? –

+0

似乎更“正确”的方法,我只是不想“删除”返回的指针。 – Fabi1816

+1

@ Fabi1816这就是智能指针('std :: shared_ptr'和'std :: unique_ptr')的用途。在现代代码中没有理由调用delete。假装关键字不存在。 – David

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(); 
} 

在主创建堆栈A B不知道他的类型。 (用C++ 11中的右值引用)

相关问题