【问题标题】:Downcast object which was instantiated with parent class用父类实例化的向下转型对象
【发布时间】:2018-11-22 17:00:52
【问题描述】:

我有一个父子继承结构。我有一个由父类实例化(新)的对象。我想将此对象向下转换为子类。 我需要一个像强制转换这样的自动例程,因为父类有很多属性,而在子对象中复制父属性是不可能的。

我可以使用 reinterpret_cast 运算符将父对象转换为子对象,这样我的子对象中有父属性值,但我遇到了其他问题。

如果您将内存分配给子特定变量之一,则在向下转换后,当您想要删除子对象时,您将面临内存分段错误错误。看来堆已损坏。

我的代码是这样的:

    class parentclass
    {
    public:
        int parent_var = 10;
        parentclass()
        {
            parent_var = 20;
        }

    };
    class childclass :parentclass
    {
    public:

        int* child_var;

        childclass()
        {

            child_var = NULL;
        }
    };
void main()
{
        parentclass* pobj = new parentclass();
        childclass* cobj;
        cobj = reinterpret_cast<childclass*>(pobj);
        //everything is ok, cobj.parent_var has correct value (=20)
        //and child specific variables are filled with random variables. 

        delete cobj;
        // cobj delete successfully


        parentclass* pobj2 = new parentclass();
        childclass* cobj2;
        cobj2 = reinterpret_cast<childclass*>(pobj2); 
        //everything is ok   and   
        //cobj2.parent_var has correct value

        cobj2->child_var = new int[10]; // assign memory to child specific variable

        delete cobj2;  // Here Heap corruption Error occurred.
}

我在 stackoverflow 中阅读了类似的页面,但其中大多数描述了使用子类新建对象时的强制转换。 感谢您的帮助。

【问题讨论】:

  • C++ 不是 C 并且 C 没有类。
  • 您使用parentclass 的对象,因为它是childclass 的对象。换一种方式就好了。您的代码调用未定义的行为。 cobj2-&gt;child_var = new int[10]; 可能会覆盖一些内部内存,这些内存在您删除对象时使用。
  • 继承不是这样工作的。当new 创建对象时,它会分配足够的内存来仅存储其元素。它对派生类一无所知。考虑改为创建子对象。还使用static_cast 将对象转换为错误的类型会产生未定义的行为。
  • 你正在做的不是一个dowcast。向下转换是当你有一个类型为parentclass * 的指针实际上指向一个类型为childclass 的对象,并且你想得到一个childclass *。你所拥有的是一个parentclass 类型的对象,你在向编译器撒谎关于它的类型。这行不通。
  • 为了给这个讨论增加一些理论,你应该看看Liskov substitution principle以更好地理解这个问题。

标签: c++ casting dynamic-cast reinterpret-cast


【解决方案1】:

在这种情况下,您不应该使用 reinterpret_cast(并尽量避免使用它),因为 reinterpret_cast 只是更改数据的解释,它不会执行任何其他操作然后更改类型

这意味着 cobj 仍然指向与 pobj 相同的数据。这就是您尝试修改child_var时代码失败的原因@

如果它是作为孩子创建的,你只能向下转换一个指针,我的意思是

parentclass* pobj = dynamic_cast<parentclass*>(new childclass()); //created as a child not a parent
childclass* cobj;
cobj = dynamic_cast<childclass*>(pobj); //dynamic_cast instead of reinterpret_cast

如果父母是公开的就可以了

class childclass : public parentclass

还有

void main() 应该是int main()

【讨论】:

  • 我明白如你所说,强制转换是不可能的,现在我该如何解决我的问题并拥有一个填充了父对象值的子对象?
  • 如果您公开继承,则无需强制转换即可访问父级的成员
  • 投反对票,因为我不相信这回答了提问者的真正问题,即他们将一种类型转换为完全不同的类型,并期望它出于某种原因能够工作。
  • @JamesPicone 我想我通过解释为什么他不能使用 reinterpret_cast 以及他需要做什么来使用 dynamic_cast 来解决这个问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-25
  • 1970-01-01
  • 2018-11-24
相关资源
最近更新 更多