C ++异常处理混乱

时间:2016-11-18 20:42:29

标签: c++ error-handling exception-handling coding-style code-cleanup

所以,基本上我有一个外部C库的简单包装代码,而且我是一个适当的异常处理新手。

事先:代码两次显示相同的问题,但也许是类版本的不同解决方案。

#include <some_c_lib>

void setup(){
    //some setup code

    //init function from the C library
    //with C-style return code for error handling
    if(!init()){ 
        //error: program should terminate
        //because error cannot be handled
    }

    //some setup code
}

class myclass{
    //some members

public:
    myclass(){
        //some construction code

        //create function of the C library
        //with C-style return code error handling
        if(!create()){
            //error: program should terminate
            //because error cannot be handled
        }
    }

    ~myclass(){
        //desturction code
    }
};

int main(){
    std::ostream log("log.txt");  //logfile as an example

    setup();

    myclass obj;

    while(everything_is_fine()){
        //main loop stuff
    }

}

问题是:我不知道终止程序的最佳方法是什么。 我不想在main中发现异常。这将是一种毫无意义和丑陋的,因为无论如何都无法处理异常。即便如此,我还想拥有某种堆栈展开机制。如果我只是exit if块内的程序,那么日志文件就不会被正确销毁。我对吗?

  • 如果我扔进if但是没有在任何地方提供try-catch块,文件会关闭吗?

  • 如何处理构造函数中发生的异常?

  • 有没有最好的方法来处理这类问题?

我希望我的问题很清楚。

感谢您的回答,祝您有个美好的一天或晚上。

2 个答案:

答案 0 :(得分:1)

这取决于你,你真的没有提供足够的信息。一般来说,没有绝对的“最佳” - 它取决于你的程序的需求,而不是“一刀切”的方法。

只有在小的琐碎程序中才会出现这种情况(例如,您在课堂练习中所做的事情,而不是工作场所),错误始终需要立即终止程序。现实世界的需求比模糊不清 - 取决于程序的功能,通常可以选择从错误中恢复并继续(正常或在某种降级模式下)。最好采取措施防止出现错误(例如检测错误数据,并在对坏数据进行操作并导致错误情况之前采取措施进行恢复)。

但是,通常情况下,如果构造函数中发生错误(并且它是不可避免的,并且构造函数在发生错误时无法执行任何操作等),则必须抛出异常。这基本上表示需要调用者(或调用堆栈中的某些函数)采取恢复操作。如果调用者无法恢复,则抛出异常的默认结果是程序终止 - 调用调用堆栈中本地(自动存储持续时间)创建的所有对象的析构函数。这会终止程序 - 如果有必要 - 并且在过程中进行清理,只要析构器正确清理(这是析构函数的目的)。

在您的代码中,抛出异常将(最终)将控制权返回给main()。如果未捕获异常,程序将终止 - 但不会在log被销毁之前终止 - 这会调用其析构函数。标准输出流类的析构函数通常会刷新流并正确关闭它。如果您需要做更多的事情(例如,在终止之前的其他恢复操作,在刷新流之后)将main()写为函数try-block。

通常不建议在构造函数中执行“部分构造” - 例如,构造函数设置一些基础知识,但用户则必须调用另一个函数来进行“进一步”初始化。这些技术是忘记进行初始化的机会 - 这基本上意味着后续代码可以使用未正确初始化的对象。在C ++中,无论如何都很少需要这样的技术 - 可以推迟创建一个对象,直到所有信息都可用于正确初始化它(在构造函数中)。

一般来说,返回错误代码(例如,具有非void返回类型的函数,接受指向存储状态信息的对象的指针/引用的函数)在不同情况下是适当的。没有任何东西迫使调用者检查函数的返回值。因此,如果可以安全地忽略错误条件(例如,如果您的代码忘记检查它),或者该函数仅用于检查返回代码的情况,则返回代码是合适的。没有什么能阻止您编写将返回代码(例如,用C编写的函数)转换为异常的代码。返回码的问题在于可能忘记检查它们 - 这可能意味着关键错误仍然未被检测到/未报告,并导致程序中其他代码出现故障。

答案 1 :(得分:0)

一种解决方案不是以这样的方式编写构造函数,以至于它们会抛出错误。通常的做法是使用构造函数来设置成员变量等,然后有一个方法,如bool initialize();返回一个值,该值基于类是否可以执行更复杂的初始化而没有错误。

除了bool之外,您还可以返回其他值或结构以获取更多信息性错误。

最后,您的日志文件仍可由任何类写入,并且如果您有任何错误,则应包含错误信息。