MST
星途 面试题库

面试题:C++析构函数重载异常处理与资源管理的协同

考虑一个复杂的C++程序,有一个`ResourceManager`类,它通过不同的析构函数重载来处理不同类型资源的释放。这些资源包括文件句柄、网络连接等。如果在释放网络连接的析构函数中抛出了一个`std::system_error`异常,如何设计一个机制,确保文件句柄等其他资源仍能被正确释放,并且异常能被上层合适的代码捕获并处理?请详细阐述设计思路并给出关键代码片段。
41.3万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. RAII原则:利用C++的RAII(Resource Acquisition Is Initialization)机制,确保每个资源在对象生命周期结束时自动释放。在ResourceManager类中,每个资源应该由对应的成员对象管理,这些成员对象本身遵循RAII原则。
  2. 异常安全:析构函数通常不应该抛出异常,因为在栈展开过程中,如果析构函数抛出异常,会导致std::terminate被调用。因此,对于可能抛出异常的资源释放操作,需要特殊处理。
  3. 局部异常处理:在释放网络连接的析构函数中,捕获std::system_error异常,确保文件句柄等其他资源正常释放。然后,重新抛出异常,以便上层代码捕获并处理。

关键代码片段

#include <iostream>
#include <stdexcept>
#include <system_error>
#include <memory>

// 模拟文件句柄类
class FileHandle {
public:
    FileHandle() { std::cout << "FileHandle created" << std::endl; }
    ~FileHandle() { std::cout << "FileHandle released" << std::endl; }
};

// 模拟网络连接类
class NetworkConnection {
public:
    NetworkConnection() { std::cout << "NetworkConnection created" << std::endl; }
    ~NetworkConnection() {
        std::cout << "NetworkConnection releasing..." << std::endl;
        // 模拟可能抛出异常的资源释放操作
        throw std::system_error(std::make_error_code(std::errc::network_down), "Network connection error");
    }
};

class ResourceManager {
private:
    std::unique_ptr<FileHandle> fileHandle;
    std::unique_ptr<NetworkConnection> networkConnection;

public:
    ResourceManager() : fileHandle(std::make_unique<FileHandle>()), networkConnection(std::make_unique<NetworkConnection>()) {}

    ~ResourceManager() {
        try {
            if (networkConnection) {
                networkConnection.reset(); // 释放网络连接,可能抛出异常
            }
        } catch (const std::system_error& e) {
            std::cerr << "Caught system_error in NetworkConnection destructor: " << e.what() << std::endl;
            // 文件句柄在离开作用域时会自动释放
            throw; // 重新抛出异常,让上层代码处理
        }
    }
};

使用示例

int main() {
    try {
        ResourceManager manager;
    } catch (const std::system_error& e) {
        std::cerr << "Caught system_error in main: " << e.what() << std::endl;
    }
    return 0;
}

在上述代码中:

  1. FileHandleNetworkConnection类分别模拟文件句柄和网络连接资源,它们的析构函数负责释放资源。
  2. ResourceManager类使用std::unique_ptr来管理FileHandleNetworkConnection对象,确保资源在ResourceManager对象析构时自动释放。
  3. ResourceManager的析构函数中,对NetworkConnection的释放操作进行异常捕获。如果捕获到std::system_error异常,先确保FileHandle能正常释放,然后重新抛出异常,以便上层代码处理。
  4. main函数中,通过try - catch块捕获并处理从ResourceManager析构函数中重新抛出的异常。