出于好奇,我试图做类似下面的例子,看看编译器是否给了我一个警告,而不是调用无限循环,最终导致堆栈溢出。我想也许有一种不同的行为,而不仅仅是调用普通的函数或方法。但事实并非如此。是否有一个特殊的解释,或者它只是作为普通的函数调用处理,因为我通过使用this
运算符明确地调用基类析构函数?
示例:
class A {
virtual ~A();
};
class B : A {
virtual ~B() { this->~A(); }
};
答案 0 :(得分:2)
@ M.M的评论命中了它。你正在两次调用析构函数。这是未定义的行为,任何事情都可能发生,包括您观察到的行为。
(实际上,很可能其中一个析构函数调用修改了对象的vptr,这意味着后续的析构函数调用不再转到最派生的对象。但这只是猜测。)
正确的做法是不要手动调用析构函数。
答案 1 :(得分:1)
派生类中的虚拟析构函数将始终首先以递归顺序调用父类析构函数,以便最多的"祖先"基类'析构函数将被调用,然后是第二个 - "祖先"等等。想象一下,Child继承自Parent,它继承自GrandParent。儿童班'析构函数实际上会调用GrandParent的析构函数,然后是Parent的析构函数,然后是Child的析构函数。
实际上,派生类构造函数也以相同的递归顺序调用其父类构造函数。您必须想象派生类,例如"图层蛋糕":每个继承实例都会为您的对象添加一个图层。所以Child类有3层{GrandParent,Parent,Child},每个层的构造/破坏都由相应的类处理。
您尝试的操作将尝试两次调用父析构函数,这是一个坏主意。通常,除了重载new
运算符的情况外,您不必显式调用析构函数。有关详细信息,请参阅此答案:Is calling destructor manually always a sign of bad design?
答案 2 :(得分:0)
调用派生类虚拟析构函数会导致调用基类析构函数。但反之亦然。