MST

星途 面试题库

面试题:C++ 中虚析构函数在继承体系下的应用场景

在一个C++ 继承体系中,基类有一些动态分配的资源,派生类也有动态分配的资源。请举例说明为什么基类的析构函数需要声明为虚函数,不声明会出现什么问题?
23.1万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

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. 不声明为虚函数出现的问题

  • 内存泄漏:如上述示例,派生类中动态分配的资源得不到释放,因为派生类的析构函数不会被调用。
  • 资源清理不完整:不仅是内存资源,如果基类和派生类中还有其他需要清理的资源(如文件句柄、网络连接等),不调用派生类析构函数会导致这些资源没有被正确关闭或清理,可能会引发程序后续运行时的错误。