C++ 动态转换异常

Posted

技术标签:

【中文标题】C++ 动态转换异常【英文标题】:C++ dynamic_cast exception 【发布时间】:2015-11-25 13:47:10 【问题描述】:

请帮助我理解奇怪的行为:

当析构函数~MyLogicObject() 正在处理时,我使用从MyObjectMyLogicObject 的dynamic_cast,但编译器抛出异常:non_rtti_object

我确定对象MyObject 是一种多态类型。我哪里错了?

#ifndef MYOBJECT_H
#define MYOBJECT_H

#include <string>

class A

    int a;
;

class B

    int b;
;

class MyObject: public A,
                public B// if comment this row, and don't use multi inheritable, everything will be fine

    private: std::string name;
    private: bool singleshot;


    public: MyObject(void);

    public: virtual ~MyObject(void);

    protected: void Destroying(void);

    public: std::string GetName(void);

    public: virtual bool Rename(std::string _newName);
;

#endif

#include "MyObject.h"
#include "MyLogicObject.h"

MyObject::MyObject(void): singleshot(true)



MyObject::~MyObject(void)

    printf("\n~my object\n");
    Destroying();



void MyObject::Destroying(void)

    if(singleshot)
     
        printf("\nexception!\n");
        dynamic_cast<MyLogicObject*>(this);// exception: non_rtti_object
        singleshot = false;
    



std::string MyObject::GetName(void)

    return name;



bool MyObject::Rename(std::string _newName)

    name = _newName;
    return true;



#ifndef MYLOGICOBJECT_H
#define MYLOGICOBJECT_H
#include "MyObject.h"

    class MyLogicObject: public virtual MyObject // if not use virtual  inheritance (instead, use the standard inheritance), everything will be fine
    
        public: MyLogicObject(void);

        public: virtual ~MyLogicObject(void);

        public: virtual void Update(float _delta = 0.0f);

        // if reimplement virtual method of base class, everything will be fine
        /*
        public: virtual bool Rename(std::string _newName)
        
            return MyObject::Rename(_newName);
        
        */ 
    ;

    #endif 

#include "MyLogicObject.h"


MyLogicObject::MyLogicObject(void)



MyLogicObject::~MyLogicObject(void)

    printf("\n~my logic object\n");
    Destroying();




void MyLogicObject::Update(float _delta)


#include <conio.h>
#include <stdio.h>
#include "MyLogicScene.h"


class C

    int c;
;



class DerivedObject: public MyLogicObject,
                     public C// if comment this row, and don't use multi inheritable, everything will be fine

    public: DerivedObject(void)
    

    public: virtual ~DerivedObject(void)
    
        printf("~derived object: %s\n", GetName().c_str());
        //Destroying(); // if call Destroying in this place, overything will be file
    
;


int main()

    DerivedObject* object1 = new DerivedObject();
    object1->Rename("object1");

    printf("delete object1...\n");
    delete object1;


    getch();
    return 0;

【问题讨论】:

从析构函数内部 MyObject 已经破坏了对象的 MyLogicObject 部分。 “但我确定对象 B 是一个多态类型。” Class B int b; ; 不是多态的。它需要定义或继承至少一个虚拟方法(例如虚拟析构函数)才能具有多态性。但在你的例子中,我认为 B 是否是多态的并不重要。 你能发布你的输出吗? 您的示例 online 似乎有效。我没有深入研究,但是在销毁期间使用虚函数是特殊的。把事情搞砸是很容易的。 尝试测试(甚至阅读)您的代码很烦人,因为您已将其拆分为许多不同的文件,这是完全没有必要的。不需要五个单独的文件来证明问题(即它不是minimal, complete, verifiable example) 【参考方案1】:

您正在尝试将基类 (MyObject) 类型的对象动态转换为派生类 (MyLogicObject)。除非基类是多态的并且启用了 rtti,否则 dynamic_cast 不允许这种转换。参考this。

所以你基本上需要在你的编译器选项中启用 rtti。 一旦完成,请确保 object1 是派生类 (MyLogicObject) 的完整对象,以便强制转换工作而不会引发异常。

它也适用于相反的情况。例如,如果您尝试将派生类 (MyLogicObject) 类型的对象动态转换为基类 (MyObject)。

【讨论】:

但我的 rtti 选项默认启用,我在 project->properties->C++->language 选项卡中检查了这个。我发现我的问题:警告 C4436:在构造函数或析构函数中从虚拟基础“MyObject”到“MyLogicObject”的动态转换可能会因部分构造的对象msdn.microsoft.com/en-us/library/jj155805.aspx 而失败 见第二段:“确保object1是派生类(MyLogicObject)的完整对象”。 它用不同的词说同样的事情。 在object1正在破坏的时候我怎么知道呢?在 gcc 上我的代码工作正常,但不是在 vs 2008/2010 我的问题似乎得到了解释。 dynamic_cast 中的偏移量计算错误。这个问题与 C++ 相比。如果清楚地实现构造函数和析构函数,一切都会好起来的。

以上是关于C++ 动态转换异常的主要内容,如果未能解决你的问题,请参考以下文章

我正在尝试将 Object 转换为动态类型,但转换失败并出现 RunTimeBinder 异常

C/C++杂记:运行时类型识别(RTTI)与动态类型转换原理

将python代码转换为c ++时出现opencvcornerSubPix异常

C# .Net 4.0 应用程序中托管的 C++ ActiveX 控件中的 Xml.Serializer 非法强制转换异常

类型转换_异常处理机制

C++的类型转换