9

我正在使用 Visual Studio 并执行有效的动态转换。RTTI 已启用。

编辑:更新代码更真实

struct base
{
    virtual base* Clone()
    {
        base* ptr = new base;
        CopyValuesTo( ptr );
        return ptr;
    }
    virtual void CopyValuesTo( base* ptr )
    {
       ...
    }
    virtual ~base()
    {
    }
}

struct derived : public base
{
    virtual base* Clone()
    {
        derived* ptr = new derived;
        CopyValuesTo( ptr );
        return ptr;
    }
    virtual void CopyValuesTo( base* ptr )
    {
       ...
    }
    virtual ~derived()
    {
    }
}  

void Class1::UseNewSpec( base* in_ptr ) //part of a totally unrelated class
{
    derived* ptr = dynamic_cast<derived *>(in_ptr);
    if( !ptr )
       return;
    delete m_ptr;
    m_ptr = ptr->Clone(); //m_ptr is a member of Class1 of type base*
}

//usage : 
Class1 obj;
derived new_spec; 
obj.UseNewSpec( &new_spec );

我的调试器说在抛出异常时 in_ptr 是正确的类型。谷歌似乎特别没有帮助。有任何想法吗?干杯。

4

5 回答 5

9

https://docs.microsoft.com/en-us/cpp/cpp/typeid-operator?view=vs-2019有关于 __non_rtti_object_exception 的信息。

来自 MSDN:

如果指针未指向有效对象,则抛出 __non_rtti_objectexception,表示尝试分析触发错误的 RTTI(如访问冲突),因为该对象在某种程度上是无效的(错误的指针或代码未编译/GR)。

于 2009-05-12T21:08:05.873 回答
6

围绕 dynamic_cast 的 RTTI 异常、失败或错误可能意味着您执行了非法转换。 dynamic_cast<derived*>(ptrToBase)当且仅当类derived和类base都满足以下约束时才有效:该类或其基类之一具有虚拟成员函数。

这个虚成员函数可以是任何东西,包括析构函数。如果您没有任何其他成员函数,您可以尝试:

struct base
{
    virtual ~base(){}
    ...
}

struct derived : public base
{
    ...
}

现在base有一个虚成员函数,派生的也有。尝试一下,看看它是否能解决您的问题。

编辑添加:

@carleeto - 在“它已经有一个虚拟析构函数”中,它是否==base?

如果派生具有虚拟析构函数但基是非虚拟 dtor,那么您仍然可能会收到此错误。

此外,您应该验证对象没有被破坏——一旦析构函数运行,调用 dynamic_cast 就不再安全了。尝试向 ctors 和 dtors 添加跟踪。

于 2009-05-12T21:06:47.433 回答
6

我根据你的伪代码运行了一个测试,它可以工作。因此,如果您的构建配置中真正启用了 RTTI,那么它一定是您发布的内容中未捕获的另一个问题。

于 2009-05-12T21:30:33.293 回答
1

确保在所有源文件中都启用了 RTTI。

否则指针无效。

于 2009-05-12T21:25:08.183 回答
0

是否base包含任何virtual方法?它必须为了dynamic_cast工作。

于 2009-05-12T21:07:23.673 回答