面试题答案
一键面试1. 示例说明基类析构函数声明为虚函数的原因
假设我们有一个基类Base
和一个派生类Derived
,如下所示:
#include <iostream>
#include <cstring>
class Base {
public:
Base() {
data = new char[10];
std::strcpy(data, "BaseData");
}
~Base() {
std::cout << "Base destructor" << std::endl;
delete[] data;
}
private:
char* data;
};
class Derived : public Base {
public:
Derived() {
derivedData = new char[10];
std::strcpy(derivedData, "DerivedData");
}
~Derived() {
std::cout << "Derived destructor" << std::endl;
delete[] derivedData;
}
private:
char* derivedData;
};
当我们使用基类指针来管理派生类对象时,如果基类析构函数不是虚函数:
int main() {
Base* ptr = new Derived();
delete ptr;
return 0;
}
输出结果只会有“Base destructor”,这意味着派生类的析构函数没有被调用,derivedData
指向的内存没有被释放,从而导致内存泄漏。
如果将基类的析构函数声明为虚函数:
class Base {
public:
Base() {
data = new char[10];
std::strcpy(data, "BaseData");
}
virtual ~Base() {
std::cout << "Base destructor" << std::endl;
delete[] data;
}
private:
char* data;
};
再次运行上述main
函数,输出结果会是“Derived destructor”和“Base destructor”,派生类和基类的析构函数都会被正确调用,资源得到释放。
2. 不声明为虚函数出现的问题
- 内存泄漏:如上述示例,派生类中动态分配的资源得不到释放,因为派生类的析构函数不会被调用。
- 资源清理不完整:不仅是内存资源,如果基类和派生类中还有其他需要清理的资源(如文件句柄、网络连接等),不调用派生类析构函数会导致这些资源没有被正确关闭或清理,可能会引发程序后续运行时的错误。