我有以下类层次结构:
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 *),但应用程序仍然崩溃......
答案 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);
Base* ptrToBase = obj;
,我已经对Base*
做了一次static_cast?
Re Mark Ransom:通过打印指针和删除操作的步骤,我看到指针始终具有相同的地址,并在~MoreDerived()
处崩溃。
Re Potatoswatter:我认为在“更有效的C ++”中他们提到使用dynamic_cast< void* >
,但我没有再找到那句话。我会试一试,让你知道结果。
再次感谢