MST

星途 面试题库

面试题:C++ 中析构函数调用顺序在继承体系下的调试

假设有一个简单的C++继承体系,基类Base和派生类Derived,Derived类继承自Base类。在Base类和Derived类中分别定义构造函数和析构函数,并在构造函数和析构函数中输出一些信息用于调试。请写出代码,并说明当Derived类对象被销毁时,析构函数的调用顺序,以及如何利用调试工具(如GDB)来验证这个调用顺序。
12.3万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

代码如下:

#include <iostream>

class Base {
public:
    Base() {
        std::cout << "Base constructor called." << std::endl;
    }
    ~Base() {
        std::cout << "Base destructor called." << std::endl;
    }
};

class Derived : public Base {
public:
    Derived() {
        std::cout << "Derived constructor called." << std::endl;
    }
    ~Derived() {
        std::cout << "Derived destructor called." << std::endl;
    }
};

main 函数中使用 Derived 类:

int main() {
    Derived d;
    return 0;
}

析构函数调用顺序:

Derived 类对象被销毁时,析构函数的调用顺序是先调用 Derived 类的析构函数,再调用 Base 类的析构函数。这是因为在对象销毁时,构造的逆过程被执行。Derived 对象构造时先调用 Base 的构造函数,然后才是 Derived 自身的构造函数,所以销毁时先 Derived 析构,再 Base 析构。

利用GDB验证调用顺序:

  1. 编译带有调试信息的程序: 使用 g++ -g 选项编译上述代码,例如:g++ -g -o test test.cpp
  2. 启动GDB: 运行 gdb test 进入GDB调试环境。
  3. 设置断点: 在 BaseDerived 的析构函数处设置断点。例如:
    (gdb) b ~Base
    (gdb) b ~Derived
    
  4. 运行程序: 使用 run 命令运行程序:(gdb) run
  5. 观察断点命中顺序: 当程序执行到对象销毁时,GDB会停在 Derived 类的析构函数断点处,此时输出信息为 Derived destructor called.。继续执行(使用 continue 命令),GDB会停在 Base 类的析构函数断点处,输出信息为 Base destructor called.。这就验证了析构函数的调用顺序。