C++ 当类型转换为指向对象的void指针时未调用析构函数

C++ 当类型转换为指向对象的void指针时未调用析构函数,c++,C++,样品 请帮我弄清楚这一点。调用了析构函数。请给我们完整的代码。总结了不调用CResource析构函数的可能原因,摘自其他答案: 不完全类型 一个可能的原因是您只声明了CResource类型,而没有定义: void func(void* data) { CResource* resource = (CResource*)data; delete resource; // ~CResource never called. resource = NULL; } 这是一种未定义的行为(删除不完整

样品


请帮我弄清楚这一点。

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

总结了不调用CResource析构函数的可能原因,摘自其他答案:

不完全类型 一个可能的原因是您只声明了CResource类型,而没有定义:

void func(void* data)
{
 CResource* resource = (CResource*)data;
 delete resource; // ~CResource never called.
 resource = NULL;
}
这是一种未定义的行为(删除不完整的类型)。在这种情况下,编译器应该发出关于未被调用的析构函数的警告(Visual C++确实发布它)。如果是这种情况,请确保在销毁它的位置定义了类型(包括所需的标题)

空指针 如果数据为NULL,delete不执行任何操作,也不调用任何析构函数

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

为什么不调用dtor? 可能是因为您在dtor中添加了printf,而没有看到任何消息

可能调用了另一个dotr?CResource是遗传的吗?你定义基类析构函数虚拟吗


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

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


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

析构函数是虚拟的吗?可能数据根本不指向CResource对象,而调用了其他类的虚拟析构函数。

我假设CResource是某种超类,您可以通过通用指针轻松传输对象

class CResource;

void func(void* data)
{
 CResource* resource = (CResource*)data;
 delete resource; // ~CResource never called.
 resource = NULL;
}
<> P>你的问题对于C++新手来说是一个普通的问题,你应该阅读< /P>


此外,还需要一份Scott Meyer的“高效C++”,因为它会让你在接下来的几个月里犯下许多错误。

必须调用析构函数。请提供CResource.com的定义,可以简单到data==0。但是我们非常需要代码来决定会发生什么:)这个问题表明我们对基本原则缺乏理解,但试图询问更高级的原则。。。。不管怎么说,它是以一种糟糕的方式完成的——代码不够完整,任何人都无法给出答案,因此需要猜测水晶球。不,不是的,在这样一个函数中不调用析构函数只有一个原因,我在回答中指出了这个原因。我确实同意,问题(标题)可能应该更改。当使用新对象创建对象时,类型信息将与在堆上创建的对象一起添加?当使用新对象创建对象时,类型信息确实将与在堆上创建的对象一起添加,但只有当对象属于至少有一个虚方法的类时,析构函数调用所需的类型信息才是静态的(编译时)。当类型未定义时,编译器不知道析构函数是否存在,或者析构函数是什么(它是虚拟的还是非虚拟的)。链接器不会处理这些吗?我的意思是,析构函数总是存在的(如果您不提供,编译器会生成默认的析构函数),所以编译器可以安全地假设析构函数存在,并且链接器会找到它。至少,这就是理解孔编译器链接器关系的方式……std明确指出,如果完整类型具有非平凡析构函数(用户定义),或者如果数据指向CResource以外的其他对象,并且CResource具有虚拟析构函数,则不完整类型指针上的删除是未定义的行为。delete将尝试从“坏”对象使用VMT,并可能随机调用其他对象。请回答一个问题。如果类有更多的虚函数,那么析构函数将是一个类中的第一个虚函数,第二个类中的第五个虚函数。土豚的毁灭者还会被召唤吗?或者它会调用其他虚拟成员吗?我只是用我的样本尝试了一下。由于析构函数是CResource中的第一个虚拟函数,这段代码实际上调用了Aardvark的vtable中的第一个函数,不管它是否是析构函数。我猜这可能属于“未定义行为”的标题,这取决于编译器是如何实现的。在Visual Studio中,析构函数始终是虚拟函数表中的第一个条目。非常有趣。。。即使您使用的是同一个类,并且您更改了函数的顺序,并且没有重建整个项目,也可能会出现微妙的错误。。。非常有趣。。。
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;
}