使用 new 运算符将对象复制到堆而不知道其类型
我有一个疑问,下面的函数可以接收类型 A 或派生类型的对象。
A *copyToHeap(A &obj) {
A *ptr=new A(obj);
return ptr;
}
如果我们这样称呼:
//B inherits from A
B bObj;
B *hPtr=copyToHeap(bObj);
hPtr
指向的对象实际上是A类型还是B类型? 这样做安全吗?
I have a doubt, the function below can receive an object of type A or something derived type.
A *copyToHeap(A &obj) {
A *ptr=new A(obj);
return ptr;
}
If we call it like this:
//B inherits from A
B bObj;
B *hPtr=copyToHeap(bObj);
The object pointed by hPtr
is actually of type A or B?
Is safe doing this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
当您在代码中执行以下操作时:
您将始终获得一个 A 实例。 obj 将被视为 A,并且将基于 obj 的“A 部分”创建新的 A。
更好的方法是如之前的回复所述,向基类添加一个虚拟 MakeCopy 方法并为派生类实现它。
此方法是通过复制其调用的对象来实现的。然后它在派生类中实现,因此如果您有一个实际上是 B 对象的 A 指针,您将获得一个真正的 B 副本,并避免示例中发生的“切片”。
when you do the below in your code:
you'll always get an A instance. obj will be treated as an A and a new A will get created based on the "A part" of obj.
The better approach is as an earlier reply indicated, add a virtual MakeCopy method to the base class and implement it for the derived classes.
This method is implemented by making a copy of the object for which its called. It then gets implemented in the derived classes so if you have an A pointer which is actually a B object you'll get a true B copy and avoid the "slicing" which is occurring in your example.
返回的对象是
pointer to A
类型,这意味着hPtr
指向的对象是A
类型。这是不安全的,因为调用 B 独有的方法或成员会导致崩溃或未定义的行为。您可能正在寻找工厂模式。The returned object is of type
pointer to A
, which means the object pointed to byhPtr
is of typeA
. It's not safe since calling methods or members exclusive to B will cause a crash or undefined behavior. You're probably looking for the factory pattern.一个安全的方法是提供虚拟克隆方法
A safe way is to provide a virtual clone method
它不安全,不正确,编译器应该给你一些诊断信息。如果使用 GCC,您是否尝试使用
g++ -Wall
进行编译?It is not safe, it is incorrect, and the compiler should give you some diagnostics. Did you try to compile with
g++ -Wall
if using GCC?无法编译:
如果将
hPtr
的类型更改为A*
,它会编译,但您仍然会得到一个A
对象。您使用的A
的默认复制构造函数将创建一个A
对象并复制B
对象中定义的字段>A,将B
部分切掉。Doesn't compile:
If you change the type of
hPtr
toA*
it compiles, but you still get anA
object. The default copy-constructor forA
which you use will create anA
object and copy the fields of theB
object which were defined inA
, slicing theB
part off.由于上面/这篇文章中描述的所有问题——如果你能避免它(我想不出你不能避免的原因)——你不应该设计你的代码来要求“
复制到堆
”。正如卢奇安指出的那样,你可能想要一家工厂。工厂首先在堆上创建对象(并返回一个智能指针来管理对象/指针/内存的生命周期)。
Because of all the problems described above/in this post -- if at all you can avoid it (and I can't think of a reason why you couldn't) -- you should not design your code to require "
copyToHeap
".As Luchian points out, you probably want a factory. The factory creates your object on the heap to begin with (and returns a smart pointer to manage the lifetime of the object/pointer/memory).