面试题答案
一键面试- 当
Base
类析构函数不是虚函数时的情况:- 当通过
Base
指针删除Derived
对象且Base
类析构函数不是虚函数时,只会调用Base
类的析构函数,Derived
类的析构函数不会被调用,这会导致Derived
类中申请的资源无法释放,从而产生内存泄漏。 - 以下是代码示例:
- 当通过
#include <iostream>
class Base {
public:
Base() { std::cout << "Base constructor" << std::endl; }
~Base() { std::cout << "Base destructor" << std::endl; }
};
class Derived : public Base {
public:
Derived() { std::cout << "Derived constructor" << std::endl; }
~Derived() { std::cout << "Derived destructor" << std::endl; }
};
int main() {
Base* ptr = new Derived();
delete ptr;
return 0;
}
- 在上述代码中,
Base
类的析构函数不是虚函数。当执行delete ptr;
时,只会调用Base
类的析构函数,输出为:
Base constructor
Derived constructor
Base destructor
- 可以看到
Derived
类的析构函数没有被调用。
- 将
Base
类析构函数定义为虚函数的情况:- 当把
Base
类的析构函数定义为虚函数时,通过Base
指针删除Derived
对象,会先调用Derived
类的析构函数,再调用Base
类的析构函数,这样就能正确释放Derived
类和Base
类中申请的资源。 - 修改后的代码如下:
- 当把
#include <iostream>
class Base {
public:
Base() { std::cout << "Base constructor" << std::endl; }
virtual ~Base() { std::cout << "Base destructor" << std::endl; }
};
class Derived : public Base {
public:
Derived() { std::cout << "Derived constructor" << std::endl; }
~Derived() { std::cout << "Derived destructor" << std::endl; }
};
int main() {
Base* ptr = new Derived();
delete ptr;
return 0;
}
- 此时执行
delete ptr;
,输出为:
Base constructor
Derived constructor
Derived destructor
Base destructor
- 可以看到
Derived
类的析构函数被正确调用,资源得到了正确释放。
所以,为了确保通过基类指针删除派生类对象时,派生类的析构函数能被正确调用,防止内存泄漏,有时需要将Base
类的析构函数定义为虚函数。