C ++ Virtual Destructor Crash

时间:2010-09-17 16:04:49

标签: c++ virtual-destructor

我有以下类层次结构:

class Base  
{  
public:  
    virtual ~Base();  
};  
class Derived : public Base  
{  
public:  
    virtual ~Derived();  
};  
class MoreDerived : public Derived  
{  
public:  
    virtual ~MoreDerived();  
};  

以及对象

Base* base = new Base();
MoreDerived* obj = new MoreDerived(*base);  

我需要使用线程删除MoreDerived对象的代码的一部分,因此必须先将其转换为void *。在线程中,我有

void KillObject(void* ptr)  
{  
    delete static_cast<Base*>(ptr);  
}  

非指针为NULL,而void* ptr IS 为MoreDerived *(或至少为Base *),但应用程序仍然崩溃......

6 个答案:

答案 0 :(得分:3)

在C ++中,强制转换通常会导致指针地址发生变化。在转换为Base *之前,您需要转换为void *,否则您有未定义的行为。 (向Void * /从Void *进行投射是可以的,但是当它返回时,它必须是两端完全相同的类型)

答案 1 :(得分:2)

如果KillObject始终删除Base *,为什么需要void *?将ptr更改为Base *并摆脱演员表。然后,如果传入的内容是Base *Derived *MoreDerived *,则可以使用。

答案 2 :(得分:2)

通过将指针强制转换为void *,您将删除编译器有关如何在继承树中上下转换的知识。当存在多个继承时,这尤其是一个问题,因为指向同一对象的两个指针不一定具有相同的值!

不要那样做。

答案 3 :(得分:2)

如果static_cast为void *则标准只保证static_cast到原始指针类型将正常工作。如前所述,您需要dynamic_cast或者首先需要static_cast到Base *然后再到void *。从void *到Base *的static_cast应该可以正常工作。

答案 4 :(得分:1)

我认为您正在考虑dynamic_cast<void*>获取指向最派生对象的指针。

您只需要删除多态类型的对象,就不需要通过void*。只需使用您拥有的任何指针和delete,无论是Base*MoreDerived对象还是MoreDerived*。不需要Kill方法。

答案 5 :(得分:0)

非常感谢你们所有的回复。

只是为了澄清情况并详细阐述代码,我在CentOS上使用gcc 4.1.2,他在static_cast中缺少类型是StackOverflow格式错误,我有

void KillObject(void* ptr)
{
delete static_cast< Base* >(ptr);
};
// There is a reason for the following as this is a snipet and stuff gets passed around
Base* base = new Base();
MoreDerived* obj = new MoreDerived( * base );
Base* ptrToBase = obj;
// Use ptrToBase in code with no problems
// Delete object, illustrative only - have to cast to void* to pass to API
pthread_run( ... , KillObject , (void*)ptrToBase);

Re Billy O'Neal:我想通过做Base* ptrToBase = obj;,我已经对Base*做了一次static_cast?

Re Mark Ransom:通过打印指针和删除操作的步骤,我看到指针始终具有相同的地址,并在~MoreDerived()处崩溃。

Re Potatoswatter:我认为在“更有效的C ++”中他们提到使用dynamic_cast< void* >,但我没有再找到那句话。我会试一试,让你知道结果。

再次感谢