三个异常处理版本,哪一个更好?

时间:2010-09-23 09:32:56

标签: c++ exception exception-handling

我正在实施一个Zip-Wrapper(zlib minizip),并问我自己应该怎么做 正确处理异常。我想的是三个版本。哪一个会 你喜欢,还是有一个我没想过的版本?

函数Install的任务是从Web服务器获取Zip文件, 解压缩其内容并删除下载的Zip文件。但如果出错了 在解压缩文件时会发生Zip-File应该删除的位置?

坦克为您的经验。

版本A(在功能外删除):

void Install() {
    getFile("upd.zip"); // Creates File
    MyZip myzip("upd.zip");
    myzip.unzip();      // Can't do its job --> Exception
    delete("upd.zip");  // In case of exception: File would not be deleted here
}

int main() {
    try {
        Install();
    }
    catch (const Error& err) {
        delete("upd.zip"); // File must be deleted here
        MessageBox(err.text);
    }
}

版本B(重新抛出异常)

void Install() {
    getFile("upd.zip"); // Creates File
    try {
        MyZip myzip("upd.zip");
        myzip.unzip();
    }
    catch (const Error& err) {
        delete("upd.zip");
        throw err; // Re-Throw the Error
    }
    delete("upd.zip");
}

int main() {
    try {
        Install();
    }
    catch (const Error& err) {
        MessageBox(err.text);
    }
}

版本C(带返回码)

void Install() {
    getFile("upd.zip"); // Creates File
    MyZip myzip("upd.zip");
    if (!myzip.unzip("upd.zip")) {
        delete("upd.zip");
        throw Error(myzip.geterror()); // what was the reason
    }
    delete("upd.zip");
}

int main() {
    // Same as in Version B
}

1 个答案:

答案 0 :(得分:3)

三者中没有一个。使用RAII

class FileGuard {
public:
    FileGurad(const std::string & filePath)
    : m_FilePath( filePath )
    {}

    ~FileGuard() {
        delete(m_FilePath); // must not throw an exception
    }
private:
    std::string m_FilePath;
};

用法:

void Install() {
    guard FileGuard(getFile("upd.zip")); // Creates File; getFile should return the path where the file was created
    MyZip myzip("upd.zip");
    myzip.unzip();      // Can't do its job --> Exception
    // file will be deleted when guard goes out of scope (e.g. when an expection is thrown)
}

或者,您可以在构造函数中FileGuard调用getFile。有关堆栈展开(尤其是破坏顺序)的更多信息,请参阅this answer(以及其他相同问题)。