初始化错误值坏样式后抛出异常?

时间:2012-11-12 22:15:00

标签: c++ exception initialization

下面的定义是坏的样式还是普通的错误?也就是说,在初始化一个被认为不正确的值之后抛出是不对的?

myClass::myClass(int arg) : value(arg)
   {
    if (value < 0)
       throw (myException("Negative value not allowed!"));
   }

似乎最好使用intializer-list而不是在正文中指定值,并且根据我的理解,如果在分配值之后抛出之前无关紧要

5 个答案:

答案 0 :(得分:5)

允许使用初始化列表的替代方法,如果参数不在有效范围内,也可以在初始化值之前抛出:

inline int RequirePositive(int value)
{    
    if (value < 0) throw (myException("Negative value not allowed!"));
    return value;
}

class myClass {
    myClass(int arg) : value(RequirePositive(arg)) {}
};

答案 1 :(得分:4)

如果value是&gt; = 0是一个类不变量,那么你真的只有几种可能性。一种方法是编写ctor以接受unsigned参数,因此值<0是不可能的。另一种是抛出异常。

但是,是的,如果用户传递了一个无法创建有效对象的值,那么抛出异常是完全可以接受的(通常是正确的做法)。构造函数的职责是创建一个有效的对象。如果它传递的值不能创建有效的对象,则异常通常是正确的响应。

至于何时抛出异常:至少在这种情况下,它并不重要。该异常将回滚创建当前对象,因此它永远不会存在。如果首先测试值要快得多,而不是复制值然后在它无效的情况下销毁它,那么它可能会有所不同。像int这样的东西几乎无关紧要。如果你有一个某种大型树,并且可以通过仅查看树的根节点来判断它是否有效,那么首先检查该节点可能会更好,并且只复制三个如果它有效。

后者显然是一种优化,但可以是足够大且足够简单的,即使没有分析也可能是值得的(可以说,它只是避免了悲观化的优化)。

答案 2 :(得分:3)

您正在使用内置类型的初始化列表,您没有获得任何性能优势,所以为什么不在构造函数体内检查后对成员变量进行赋值。在您的情况下,您有一半创建非法对象而不是一半创建的合法对象。那么为什么要给对象任何无效状态,只是稍后被破坏。

可以从构造函数中抛出异常(在大多数情况下,使用析构函数不是这样)。 如果你不能对他们传入的值做任何有意义的事情,即将任何负值碰到0,那么抛出一个异常似乎是要做的事情,毕竟你不能创造一个合法的对象。

你可以使用unsigned int吗? 0到4,294,967,295。使调用者更明确地表示值必须> 0.

答案 3 :(得分:0)

除非该类在紧密循环中多次初始化,否则额外函数c的性能损失可以忽略不计。这与初始化阶段不正确的损失相比,这是一个非常小的代价!特别是考虑到“坏值”可能是用户输入的结果,因此生成的问题很难报告/排除故障

答案 4 :(得分:-1)

我不会这样做。只需使用使用您班级的人员将理解这是使用它的明智的方法。