具有继承的元素的容器副本
Container copy of elements with inheritance
所有,这似乎是一个简单的问题,但它给了我适合。 假设我有一个名为 Animal 的C++基类和派生类 Cat、Dog、Horse、Hippo、Snake。 我还有另一个叫做 Zoo 的类,它包含一个 Animal 对象的列表(在本例中为 Qt List,其中基类 Animal 是 QObject)。 现在我想做的是创建一个 Zoo 对象并能够将其复制到另一个 Zoo 对象,并让目标 Zoo 拥有自己的动物副本。 问题出在 Zoo 复制构造函数中,因为它认为它有一个动物列表,它调用动物的复制构造函数,而不是编译器应该做的狗、猫等。 为了解决这个问题,我将动物列表更改为动物指针列表,然后创建了我自己的动物复制构造函数和赋值运算符。 其中每一个都调用 Animal::Clone( Animal &rhs ) 方法,该方法又调用 Animals Clone() 方法的每个派生类,该方法返回从堆中分配的新指针及其数据副本。 这一切都很好,但我一直认为我错过了一个更优雅的解决方案。 所以我的问题是,当你有一个包含类型对象的容器时,我们如何复制包含容器的类? 我希望这是有道理的。
你所做的几乎是C++的惯用方式。虚拟clone()
方法实际上称为虚拟复制构造函数惯用法。通常,您会将其声明为以下签名的虚拟抽象方法。
Animal * clone() const = 0;
请注意,它不接受任何rhs
参数,它只是返回自身的克隆。给定一个动物Animal * myPet
的实例,你可以通过说得到一个重复的
Animal * mySecondPet = myPet->clone();
如果要实例化派生类,则必须在派生类中实现它。
[Ed:] 正如你所发现的,由于C++设计中固有的切片问题,容器类不可能直接而不是通过指针来保存项目。
在C++,你的解决方案是一个成语:它就像它得到的那样优雅,每个看到它的人,知道他们C++的人,都应该立即知道你的意思。习语和某些设计模式是语言的一部分。你不能称自己精通一种语言,无论是人类还是编程语言,而不了解习语。
在我的许多项目中,我使用一个名为 Cloneable
的接口类(所有抽象虚拟方法),它仅包含此克隆方法。然后很容易强制某些基类是可克隆的:只需从可克隆继承即可。例如,我希望QEvent
是这样Cloneable
的。实际上,不可能复制QEvents
将它们发布到多个事件队列。
Daniel的建议"你试过为Animal制作虚拟的复制构造函数吗?"不能从字面上理解。实际上,在C++中没有虚拟复制构造函数或任何构造函数这样的东西 - 原因很简单:在构造对象之前,其虚拟方法表尚未最终确定。具体来说,Animal 构造函数中的代码将在调用任何派生类的构造函数以将虚拟方法表指针换出派生类中的指针之前执行。因此,如果您在构造函数中进行任何虚拟方法调用,它们将不会转到从您的类派生的任何类。 就是这样。
- Mongodb c++驱动程序:如何查询元素的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 使用strcpy将char数组的元素复制到另一个数组
- C++基于范围的 for 循环和元素副本
- 是否可以在并行区域中为共享 2D 数组创建选定元素的线程本地副本?(共享,私有,障碍:OPenMP)
- 传递给 std::for_each 的函数是否允许制作序列元素的副本?
- 创建std :: vector减去一个元素的副本的最快方法
- 我的代码正在制作 2D 数组元素的重复副本.代码中有什么问题?
- 是否可以将向量初始化为附加额外元素的另一个向量的副本
- 数组元素的本地副本
- unique()似乎正在添加最后一个元素的另一个副本
- 具有继承的元素的容器副本
- 创建由shared_pointers向量的元素所指向的对象的副本
- 创建映射元素时,请避免使用值副本
- 从计数和元素值初始化 std::vector 与副本
- 如何在构造具有不同类型元素的向量副本时显式转换
- 当向vector中添加元素时,如何知道将生成该对象的副本
- 制作副本和从副本弹出后矢量的最后一个元素发生变化
- 当修改数组中的类元素时,它的行为就像是副本,而不是引用
- 使用std::nth_element时,第n个元素的副本总是连续的