繁体   English   中英

不确定何时在C ++中使用异常

[英]Not sure when to use exceptions in C++

经过多年用C ++编写科学软件的代码,我似乎还不习惯异常,我不知道何时应该使用它们。 我知道使用它们来控制程序流是一个很大的禁忌,但除此之外......请考虑以下示例(摘自表示图像蒙版的类,并允许用户将区域添加为多边形):

class ImageMask
{
public:
    ImageMask() {}
    ImageMask(const Size2DI &imgSize);

    void addPolygon(const PolygonI &polygon);

protected:
    Size2DI imgSize_;
    std::vector<PolygonI> polygons_;
};

此类的默认构造函数创建一个无用的实例,其图像大小未定义。 我不希望用户能够将多边形添加到这样的对象。 但我不知道如何处理这种情况。 当大小未定义,并调用addPolygon()时,我应该:

  1. 默默地回来,
  2. 断言(imgSize_.valid)以使用此类检测代码中的违规并在发布之前修复它们,
  3. 抛出异常?

大部分时间我都会选择1)或2)(取决于我的心情),因为在我看来,例外是昂贵的,混乱的,并且对于这样一个简单的场景来说简直太过分了。 请问有些见解?

一般规则是当您无法执行所需操作时抛出异常。 所以在你的情况下,是的,当调用addPolygon并且大小未定义或不一致时抛出异常是有意义的。

悄悄回归几乎总是错误的做法。 assert不是一个好的错误处理技术(它更像是一种设计/文档技术)。

但是,在您的情况下,重新设计界面以使错误条件不可能或不太可能更好。 例如,像这样:

class ImageMask
{
public:
    // Constructor requires collection of polygons and size.
    // Neither can be changed after construction.
    ImageMask(std::vector<PolygonI>& polygons, size_t size);
}

或者像这样

class ImageMask
{
public:
    class Builder
    {
    public:
        Builder();
        void addPolygon();
    };

    ImageMask(const Builder& builder);
}

// used like this
ImageMask::Builder builder;
builder.addPolygon(polyA);
builder.addPolygon(polyB);
ImageMask mask(builder);

我会尽量避免任何可能创建处于某种无用状态的数据的情况。 如果你需要一个非空的多边形,那么不要让空的多边形被创建,你可以省去很多麻烦,因为编译器会强制没有空的多边形。

我从不使用静默返回,因为它们隐藏了错误,这使得发现错误比它必须复杂得多。

当我检测到程序处于只能进入的状态时,如果软件中存在错误,我会使用断言。 在您的示例中,如果您检查带有Size2DI的c'tor,该大小不为空,而不是断言存储的大小是否为空,对于检测错误很有用。 断言不应该有副作用,必须可以删除它们,而不改变软件的行为。 我发现它们非常有用,可以找到我自己的bug和文档,对象/函数的当前状态等。

如果很可能,一个函数的调用者将直接处理运行时错误,我会使用传统的返回值。 如果很可能,这个错误情况必须通过调用堆栈的几个函数调用进行通信,我更喜欢异常。 有疑问我提供两个功能。

亲切的问候托斯滕

对我来说,1是无选择。 无论是2还是3,取决于程序/库的设计,是否考虑(和文档)默认构建图像蒙版,然后添加多边形对组件的有效或无效使用。 这是一个重要的设计决策。 我建议阅读马修威尔逊的这篇文章

请注意,您有更多选择:

  • 创建自己的断言,始终调用std :: terminate并执行其他日志记录
  • 禁用默认构造函数(正如其他人已经指出的那样) - 这是我的最爱
  1. “默默回归” - 这是真正的“大禁忌”。 该程序应该知道什么是错的。
  2. “断言” - 第二条规则是仅在正常程序的流程无法恢复时断言。
  3. “扔异常” - 是的,这是正确而好的技巧。 只需要注意异常安全。 关于GotW的异常安全编码有很多文章。

不要害怕例外。 他们不咬人。 :)如果你能够充分利用这项技术,那么你将成为一名强大的程序员。 ;)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM