MST

星途 面试题库

面试题:C++中析构函数设为虚函数的场景及原理

在C++中,什么情况下需要将析构函数声明为虚函数?请举例说明,并阐述其实现原理。
42.7万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试
  1. 需要将析构函数声明为虚函数的情况
    • 当一个类可能会被继承,并且通过基类指针或引用删除派生类对象时,需要将基类的析构函数声明为虚函数。这样做是为了确保在通过基类指针删除派生类对象时,能够正确调用派生类的析构函数,避免内存泄漏等问题。
  2. 举例说明
#include <iostream>
class Base {
public:
    Base() { std::cout << "Base constructor" << std::endl; }
    // 若不声明为虚析构函数,会有问题
    virtual ~Base() { std::cout << "Base destructor" << std::endl; } 
};
class Derived : public Base {
private:
    int* data;
public:
    Derived() {
        data = new int(10);
        std::cout << "Derived constructor" << std::endl;
    }
    ~Derived() {
        delete data;
        std::cout << "Derived destructor" << std::endl;
    }
};
int main() {
    Base* ptr = new Derived();
    delete ptr;
    return 0;
}
  • 在上述代码中,如果Base类的析构函数不是虚函数,当执行delete ptr;时,只会调用Base类的析构函数,而不会调用Derived类的析构函数,这样Derived类中分配的data内存就无法释放,导致内存泄漏。将Base类的析构函数声明为虚函数后,通过Base类指针删除Derived类对象时,会先调用Derived类的析构函数,再调用Base类的析构函数,从而正确释放资源。
  1. 实现原理
    • 当一个类中有虚函数时,编译器会为该类生成一个虚函数表(vtable)。虚函数表是一个函数指针数组,存储了类中虚函数的地址。每个对象中都会包含一个指向虚函数表的指针(vptr)。
    • 当通过基类指针或引用调用虚函数时,实际调用的函数是根据对象的实际类型(即vptr指向的虚函数表中的函数)来确定的。对于虚析构函数也是如此,在删除对象时,通过对象的vptr找到对应的虚析构函数并调用,从而保证能正确调用到派生类的析构函数,进而完成整个对象层次结构的清理工作。