MST
星途 面试题库

面试题:C++ 委托构造在复杂继承体系中的应用及问题

假设有一个多层继承的 C++ 类体系,顶层基类有多个构造函数,中间层和底层子类也有各自的构造函数且存在委托构造情况。请阐述这种复杂体系下委托构造可能出现的问题,例如内存泄漏、虚函数表初始化等,并给出解决方案。同时编写相应的代码框架来描述该场景。
45.7万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

委托构造可能出现的问题

  1. 内存泄漏
    • 问题描述:如果在委托构造过程中,对象部分构造完成后抛出异常,而资源(如动态分配的内存)没有正确释放,就会导致内存泄漏。例如,在一个子类构造函数委托给基类构造函数时,基类构造函数分配了内存,若子类构造函数后续操作抛出异常,而没有在异常处理中释放基类分配的内存,就会出现内存泄漏。
    • 解决方案:使用智能指针管理动态分配的资源。智能指针在对象析构时会自动释放所管理的资源,从而避免内存泄漏。例如,使用std::unique_ptrstd::shared_ptr
  2. 虚函数表初始化
    • 问题描述:在多层继承委托构造中,虚函数表的初始化顺序可能会导致问题。在构造函数调用过程中,对象处于部分构造状态,虚函数表可能还未完全正确初始化。如果在这个过程中调用虚函数,可能会导致未定义行为。
    • 解决方案:避免在构造函数中调用虚函数。如果确实需要在构造过程中执行与虚函数类似的操作,可以通过模板方法模式等设计模式来实现。在构造函数中调用一个非虚的初始化函数,该函数可以被子类重写来完成特定的初始化操作。

代码框架示例

#include <memory>
class TopBase {
public:
    // 顶层基类构造函数
    TopBase(int value) : data(new int(value)) {
        // 这里假设 data 是动态分配的内存
    }
    TopBase(const TopBase& other) : data(new int(*other.data)) {
    }
    ~TopBase() {
        delete data;
    }
private:
    int* data;
};

class MiddleClass : public TopBase {
public:
    // MiddleClass 委托构造函数
    MiddleClass(int value) : TopBase(value) {
        // 可以在这里添加 MiddleClass 特定的初始化
    }
    MiddleClass(const MiddleClass& other) : TopBase(other) {
        // 可以在这里添加 MiddleClass 特定的拷贝初始化
    }
};

class BottomClass : public MiddleClass {
public:
    // BottomClass 委托构造函数
    BottomClass(int value) : MiddleClass(value) {
        // 可以在这里添加 BottomClass 特定的初始化
    }
    BottomClass(const BottomClass& other) : MiddleClass(other) {
        // 可以在这里添加 BottomClass 特定的拷贝初始化
    }
};

使用智能指针改进后的代码框架

#include <memory>
class TopBase {
public:
    // 顶层基类构造函数
    TopBase(int value) : data(std::make_unique<int>(value)) {
    }
    TopBase(const TopBase& other) : data(std::make_unique<int>(*other.data)) {
    }
    // 注意这里不需要显式析构函数,因为 std::unique_ptr 会自动管理内存
private:
    std::unique_ptr<int> data;
};

class MiddleClass : public TopBase {
public:
    // MiddleClass 委托构造函数
    MiddleClass(int value) : TopBase(value) {
        // 可以在这里添加 MiddleClass 特定的初始化
    }
    MiddleClass(const MiddleClass& other) : TopBase(other) {
        // 可以在这里添加 MiddleClass 特定的拷贝初始化
    }
};

class BottomClass : public MiddleClass {
public:
    // BottomClass 委托构造函数
    BottomClass(int value) : MiddleClass(value) {
        // 可以在这里添加 BottomClass 特定的初始化
    }
    BottomClass(const BottomClass& other) : MiddleClass(other) {
        // 可以在这里添加 BottomClass 特定的拷贝初始化
    }
};