使用 new 运算符将对象复制到堆而不知道其类型

发布于 2024-12-14 10:34:18 字数 283 浏览 5 评论 0原文

我有一个疑问,下面的函数可以接收类型 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

临风闻羌笛 2024-12-21 10:34:18

当您在代码中执行以下操作时:

A* ptr = new A(obj);

您将始终获得一个 A 实例。 obj 将被视为 A,并且将基于 obj 的“A 部分”创建新的 A。

更好的方法是如之前的回复所述,向基类添加一个虚拟 MakeCopy 方法并为派生类实现它。

virtual A* MakeCopy();

此方法是通过复制其调用的对象来实现的。然后它在派生类中实现,因此如果您有一个实际上是 B 对象的 A 指针,您将获得一个真正的 B 副本,并避免示例中发生的“切片”。

when you do the below in your code:

A* ptr = new A(obj);

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.

virtual A* MakeCopy();

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.

十级心震 2024-12-21 10:34:18

返回的对象是pointer to A类型,这意味着hPtr指向的对象是A类型。这是不安全的,因为调用 B 独有的方法或成员会导致崩溃或未定义的行为。您可能正在寻找工厂模式

The returned object is of type pointer to A, which means the object pointed to by hPtr is of type A. 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.

笑看君怀她人 2024-12-21 10:34:18

一个安全的方法是提供虚拟克隆方法

#include <memory>

class Base
{
public:
    virtual std::unique_ptr<Base> Clone() = 0;
};

class Derived : public Base
{
public:
    Derived(int i) : i_(i)
    {

    }

    std::unique_ptr<Base> Clone()
    {
        return std::unique_ptr<Derived>(new Derived(i_));
    }

private:
    int i_;
};


std::unique_ptr<Base> copyToHeap(std::unique_ptr<Base> obj) 
{
    return obj->Clone();
}

A safe way is to provide a virtual clone method

#include <memory>

class Base
{
public:
    virtual std::unique_ptr<Base> Clone() = 0;
};

class Derived : public Base
{
public:
    Derived(int i) : i_(i)
    {

    }

    std::unique_ptr<Base> Clone()
    {
        return std::unique_ptr<Derived>(new Derived(i_));
    }

private:
    int i_;
};


std::unique_ptr<Base> copyToHeap(std::unique_ptr<Base> obj) 
{
    return obj->Clone();
}
旧时光的容颜 2024-12-21 10:34:18

它不安全,不正确,编译器应该给你一些诊断信息。如果使用 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?

浪漫之都 2024-12-21 10:34:18

无法编译:

B *hPtr=copyToHeap(bObj); //error: invalid conversion from ‘A*’ to ‘B*’

如果将 hPtr 的类型更改为 A*,它会编译,但您仍然会得到一个 A 对象。您使用的 A 的默认复制构造函数将创建一个 A 对象并复制 B 对象中定义的字段>A,将B部分切掉。

Doesn't compile:

B *hPtr=copyToHeap(bObj); //error: invalid conversion from ‘A*’ to ‘B*’

If you change the type of hPtr to A* it compiles, but you still get an A object. The default copy-constructor for A which you use will create an A object and copy the fields of the B object which were defined in A, slicing the B part off.

〆一缕阳光ご 2024-12-21 10:34:18

由于上面/这篇文章中描述的所有问题——如果你能避免它(我想不出你不能避免的原因)——你不应该设计你的代码来要求“复制到堆”。

正如卢奇安指出的那样,你可能想要一家工厂。工厂首先在堆上创建对象(并返回一个智能指针来管理对象/指针/内存的生命周期)。

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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文