几乎所有代码示例代码都忽略了错误处理(因为它“混淆了示例代码正在解决的问题”)。我的编程知识主要来自书籍和网站,你很少在那里看到任何错误处理,更不用说好东西了。
哪些地方可以看到C ++错误处理代码的好例子?特定的书籍,特定的开源项目(最好有文件和功能可供查看),以及特定的网页或网站都将被感激地接受。
答案 0 :(得分:42)
Herb Sutter和Andrei Alexandrescu的书C++ Coding Standards附有关于错误处理和例外的整章,包括
每个主题还包含一个示例,我发现它是一个非常有价值的资源。
答案 1 :(得分:13)
“使用例外”与“使用错误代码”绝不像示例所示那样明确。
对程序流使用错误代码。如果您遇到预期的错误,请不要抛出异常。例如。你正在阅读一个文件,你可能会抛出“找不到文件”,“文件已锁定”;但是永远不要为“文件结尾”投一个。
如果这样做,你永远不能编写简单的循环,你总是将代码包装在异常处理程序中。并且不要忘记异常非常慢,这在大型多线程服务器中尤其重要。 (在桌面应用程序中根本不那么重要)。
其次,要非常小心异常层次结构。您可能认为拥有Exception
类,然后从中派生NetException
,然后为您的SMTP类SMTPException
派生。但除非您在基类中保存通用数据,否则您将始终必须捕获该层次结构中的每种类型的异常。例如。如果您在SMTPException
课程中列出SMTP错误的原因,则必须抓住它 - 如果您只捕获Exception
类别,则无法访问SMTPException
成员。解决此问题的一个好方法是在基本异常类中使用字符串和int成员,并且仅使用它们,即使对于派生类型也是如此。不幸的是std::exception
只提供一个字符串:(
有人说这样做意味着你可能只有一个异常类型,特别是因为你总是会捕获基类类型。
如果您确实使用了例外,则必须使用比使用错误代码更多的数据来填充它们。如果出现错误,您必须立即处理它们,否则它们会在代码中丢失。除了一个例外,它可能会被抛到很多位置 - 就像Roddy的例子一样。调用DoC
,从DoA
获取2个级别的异常。除非您指定错误特定于DoA
中的代码,否则您可能会认为它是从DoB
函数抛出的。 (简单的例子,但是我已经看到了代码,其中异常被处理了调用堆栈的许多级别。它是一个b st rd来调试。这尤其适用于OO程序)
所以希望,我已经给了你足够的思考。事情的简单事实是,风格在错误处理方面没有任何意义,实用性就是一切。如果必须在任何地方放置日志语句,则可能会发生错误,然后执行此操作。更重要的是,您可以看到代码出错的地方(以及正在处理的数据),而不是您拥有优雅的异常层次结构,或者您已经使用异常处理程序填充了代码。 如果您无法轻松跟踪错误,则错误处理代码无效。
例外是好的,使用它们。但想想你正在做什么,不要滥用或过度使用它们。一个误用的异常比没有错误处理更糟糕(因为你可以抓住一个崩溃转储并查看未处理的异常以便在几秒钟内找到错误。有一个被吃掉和被忽略的例外,你就被塞满了。)
多年来我发现调试的最大助手是日志记录。写日志,写出大量日志。
答案 2 :(得分:6)
我更喜欢本文中讨论的异常处理。它可以生成干净的代码,避免显式创建/删除对象,只是为了处理异常。 http://www.informit.com/articles/article.aspx?p=373339
答案 3 :(得分:4)
使用C ++,你最终会得到不太明显的错误处理代码,因为你可以把很多繁重的工作留给Exceptions。
在我看来,最基本的例外规则(也是一个最常见的规则)就是这样。 除非您有特定的计划来处理异常,否则不要尝试捕获异常。
除了异常之外,您不必担心函数返回的错误代码,因为设计良好的函数只会抛出异常。
在C中,典型的错误处理方案如下所示:
int DoA()
{
if (location == hellInAHandcart)
return ERROR;
else
RETURN OK;
}
int DoB()
{
int err = DoA();
if (err != OK)
return err;
else
return DoSomethingElse1();
}
int DoC()
{
int err = DoB();
if (err != OK)
//Handle My error here in whatever way...
}
在C ++中......
void DoA()
{
if (location == hellInAHandcart)
throw Exception("Gone To Hell in a Handcart");
}
void DoB()
{
DoA();
DoSomethingElse1();
}
void DoC()
{
try
{
DoB();
}
catch (Exception &E)
{
// Handle My error here in whatever way...
}
}