代码之家  ›  专栏  ›  技术社区  ›  Christian Ammer

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

  •  1
  • Christian Ammer  · 技术社区  · 14 年前

    我正在实现一个Zip包装器(zlib miniZip),并问自己应该如何做 正确处理异常。我在想三个版本。哪一个会 你更喜欢,还是有我没想到的版本?

    功能的任务 Install 从Web服务器获取zip文件, 解压缩其内容并删除下载的zip文件。但是如果一个错误 在解压缩文件时发生,应在何处删除zip文件?

    你的经验坦克。

    版本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 回复  |  直到 14 年前
        1
  •  3
  •   Community iksemyonov    7 年前

    三个都没有。使用 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 (和其他同一问题)了解更多有关堆栈展开的信息(特别是销毁顺序)。