【问题标题】:What are the alternatives to throwing an exception in C++在 C++ 中抛出异常的替代方法是什么
【发布时间】:2019-09-22 02:53:51
【问题描述】:

我最近面试了一家公司进行实习。他们让我写一个递归函数来计算给定整数的阶乘。所以我在纸上写了这样的东西:

int factorial(int n){
    if(n<0){throw std::invalid_argument( "received negative value" );}
    if(n == 0){return 1;}
    else{
        return n * factorial(n-1);
    }
}

然后作为后续,他们问了我一些问题

“抛出异常对这个函数的用户有什么责任?”

“你能用其他方式处理这个吗?”

“你能优雅地处理它吗?”

我真的不知道他们在寻找/暗示什么。如果我在这里遗漏了什么,谁能告诉我?

【问题讨论】:

    标签: c++ error-handling


    【解决方案1】:

    检查异常的要求要求调用者捕获和处理异常,这会使他们的代码变得混乱,并且还会增加处理异常的处理开销。

    还有其他一些方法可以在不引发异常的情况下返回。

    • 数字的阶乘不能为零或负数,因此您可以返回 0 或负整数(即“幻数”)来表示该阶乘不存在或找不到。同样,如果输入太大而无法计算int 范围内的阶乘,您也可以返回此无效值,或将特定值设置为指示故障模式的值(例如,0 表示输入负数,- 1 表示输入太大,-2 表示任何其他异常)。
    • 您可以更改方法签名以将指针返回到int,并将逻辑设置为返回NULL 以指示没有结果(C 代码经典填充为“检查 null在调用以确保它成功“逻辑之后)。如果您找到阶乘,则返回指向持有该值的 int 的指针,该值是使用 new 在堆上创建的。
    • 您可以接受short int 作为输入参数,从而消除许多(但不是全部)阶乘太大而无法适应返回值的输入值。这不会完全解决问题,但每一点都有帮助。结合另一种方法,您可以进一步减少潜在的故障模式。

    上面的第一个选项可以是优雅的,因为它允许调用者以多种方式使用该值(例如打印它,在进一步的数学运算中使用它)而无需输入非-数字或没有数字要处理。缺点是你可能会得到一个毫无意义的数字。在某些情况下,输出“建筑物中的楼层数:-1,成本:$-1”比在重要的演示中崩溃要好!类似的情况(在业务规则方面无效但可以处理数据,在这种情况下是指针)在超级马里奥兄弟中产生了著名的负世界错误!

    最后一个值更加优雅,因为它有助于防止无效数据甚至获取到函数中。正如他们所说,垃圾进,垃圾出。

    【讨论】:

    • 那么int 究竟会在哪里被指向呢?这在多线程程序中如何工作?你确定这是这里唯一的错误条件(提示,不是,至少还有一个其他明显的错误条件)?
    • @SamVarshavchik 我回复了。这些是基本面试环境中最明显​​的答案。当然你可以找到更多。
    • 另外请记住,OP 说这是为了实习。这不是一个超级大师的机会。
    • 使输入参数 unsigned 实际上并不能防止无效值进入函数。它实际上使它们无法在运行时从函数内部检测到。完全可以将负值传递给 unsigned 参数,它会自动转换为相应的(但不同的)无符号值。这意味着调用代码必须在调用函数之前预先检查该值。
    • @RobertColumbia 谢谢你的回答。事实上,当我第一次编写代码时,我只是为负输入返回 -1。后来根据他们的问题,我改成了抛出异常!第二个和第三个选项对我来说是新的,也许这就是他们想要的。谢谢大家!
    猜你喜欢
    • 2018-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-28
    • 1970-01-01
    相关资源
    最近更新 更多