在下面的代码中,删除destruct类中的基类对象时,没有任何类的析构函数被执行。这可能是什么原因? “删除obj”调用的是哪个析构函数?
#include <iostream>
using namespace std;
class base;
class destruct{
public :
destruct() {
cout<<"Destruct Constructor called"<<endl;
}
void destructObj(base* obj) {
delete obj;
}
~destruct() {
cout<<"Destruct Destructor called"<<endl;
}
};
class base {
int runs;
public:
base(){
cout<<"Constructor called"<<endl;
}
~base(){
cout<<"destructor called"<<endl;
}
};
int main() {
base *obj = new base();
destruct *desObj = new destruct();
desObj->destructObj(obj);
return 0;
}
我希望至少有一个运行任何类的析构函数。 请帮助我找出在这种情况下删除运算符的工作方式。
答案 0 :(得分:2)
问题是destruct::destructObj
需要了解Base
的定义才能知道有一个析构函数要调用,但是它所具有的只是一个前向声明。
将您的代码更改为此即可。
#include <iostream>
using namespace std;
class base;
class destruct{
public :
destruct() {
cout<<"Destruct Constructor called"<<endl;
}
void destructObj(base* obj);
~destruct() {
cout<<"Destruct Destructor called"<<endl;
}
};
class base {
int runs;
public:
base(){
cout<<"Constructor called"<<endl;
}
~base(){
cout<<"destructor called"<<endl;
}
};
// *** this function after base has been defined ***
inline void destruct::destructObj(base* obj) {
delete obj;
}
int main() {
base *obj = new base();
destruct *desObj = new destruct();
desObj->destructObj(obj);
return 0;
}
现在这让我感到惊讶,我想知道它是否是g ++扩展。当您尝试delete
指向仅具有前向声明的类的指针时,会发生编译器错误。但是我可能错了。
更新:显然,这(删除指向不完整类的指针)是未定义的行为,我想这暗示它应该编译。但是,您的编译器确实应该向您发出警告,告诉您存在问题。始终注意编译器警告,并始终在启用警告的情况下进行编译。
答案 1 :(得分:1)
当delete obj
是指向不完整类型的指针时,您正在调用obj
。这是未定义的行为(在实践中,通常通常表示不调用析构函数,但是可能发生任何事情)。
您需要将base
的定义上移到调用delete
的函数可见的地方。