当类型转换void指针指向对象时,析构函数不会被调用

时间:2008-12-17 09:08:54

标签: c++

样品

void func(void* data)
{
 CResource* resource = (CResource*)data;
 delete resource; // ~CResource never called.
 resource = NULL;
}

请帮我弄明白。

7 个答案:

答案 0 :(得分:11)

总结可能无法调用CResource析构函数的原因,从其他答案中提取:

不完整类型

一个可能的原因是您只声明了CResource类型,未定义:

class CResource;

void func(void* data)
{
 CResource* resource = (CResource*)data;
 delete resource; // ~CResource never called.
 resource = NULL;
}

这是一种未定义的行为(删除不完整的类型)。在这样的情况下,编译器应该发出关于未调用析构函数的警告(Visual C ++肯定会发出它)。如果是这种情况,请确保在您要销毁它的地方定义了类型(包括所需的标题)。

空指针

如果data为NULL,则delete不执行任何操作,也不会调用任何析构函数。

类型不匹配

如果CResource析构函数是虚拟的,并且 data 指向的内存中存储的对象实际上是不同的类型,则会得到未定义的行为。通常会调用不同的析构函数(如果对象具有另一个虚拟析构函数),在其他情况下程序可能会崩溃(如果对象没有虚拟析构函数)。

答案 1 :(得分:6)

为什么不调用析构函数的唯一原因是数据指针是0(或NULL)。这就是删除的工作原理 - 它检查指针是否为0,如果不是,则调用必要的析构函数并释放内存。

正如评论中指出的那样。还有另一个原因就是它不会被调用。如果数据指向其他类(而不是CResource)对象,并且两个类都有虚拟析构函数,那么将调用该另一个类的析构函数。

答案 2 :(得分:3)

析构函数是虚拟的吗?也许数据根本不指向CResource对象,并且正在调用其他类的虚析构函数。

答案 3 :(得分:2)

class Aardvark
{
public:
    virtual ~Aardvark()
    {
        printf("Aardvark::~Aardvark\n");
    }
};

class CResource
{
public:
    virtual ~CResource()
    {
        printf("CResource::~CResource\n");
    }
};

void func(void* data)
{
    CResource* resource = (CResource*)data;
    delete resource; // ~CResource never called.
    resource = NULL;
}

int _tmain()
{
    void *data = new Aardvark();
    func( data );
    return 0;
}

答案 4 :(得分:0)

调用析构函数。给我们完整的代码。

答案 5 :(得分:0)

为什么你说dtor没有被叫? 可能是因为你在你的dtor中添加了printf,而你没有看到任何消息?

可能还会调用另一个dotr? CResource继承了吗?您是否定义了基类析构函数虚拟?

正如rajKumar指出的那样,给我们完整的代码,我们会尽力帮助你。

答案 6 :(得分:0)

我假设CResource是某种类的超类,允许您通过通用指针轻松传输对象。

那么你的问题对于C ++新手来说是正常的,你应该阅读

http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.7

此外,请获取Scott Meyer的“Effective C ++”副本,因为它会向您介绍您将在接下来的几个月内犯下的许多错误。