我可以在这个 C++ 程序中使用异常作为递归函数而不是使用 goto

问题描述

#include <bits/stdc++.h>
using namespace std;


int exp(int b){
    try{
        throw b;
    }
    catch(int b){
        cout<<"Enter b again : ";
        cin>>b;
    }
    if(b==0)
        exp(b);    //this is the part where I think a logical error is occuring
    return b;
}

int main(){
    system("cls");
    int a,b;
    cout<<"Enter a: ";
    cin>>a;
    cout<<"Enter b: ";
    cin>>b;
    if(b==0)
        exp(b);
    cout<<"Division a/b = "<<a/b<<endl;
    return 0;
}

我试图避免在这个程序中使用 goto 函数,而是在这个程序中使用异常作为递归函数,但它显示输出是这样的

Enter a: 6
Enter b: 0
Enter b again : 0 
Enter b again : 7 
Enter b again : 5 
Enter b again :

解决方法

你可以用 C++ 做很多事情。这并不意味着您应该这样做。对非异常事件使用异常就是其中之一。正如 the C++ Core Guidelines 中所说:

将错误处理与“普通代码”分开。 C++ 实现往往基于异常罕见的假设进行优化。

简而言之,异常处理非常慢。异常对许多 C++ 程序员很有用,因为它们启用了不会减慢正常执行速度的错误处理;仅在错误实际发生时花费时间。

,

您显然不了解 try - catch 语句的工作原理。当程序的执行流程到达 throw 语句时,将考虑最近输入的 try-catch 语句的适当 catch() 块。在您的情况下,您有一个无条件的 throw,因此您的函数相当于此代码,不需要 try-catch:

int exp(int b)
{
    cout<<"Enter b again : ";
    cin>>b;

    if(b==0)
        exp(b);    //this is the part where I think a logical error is occuring
    return b;
}

因此,您要求再次输入 b,如果 b 为零,则要求再次输入...并在 b 不为零时退出循环,但它总是提示输入一个值。所有这些都可以通过单个 do .. while 完成而不需要递归,显然你必须在输入提示之前检查 b 的值,你会错过第一次输入的结果。

第二,您实际上并没有返回用户值,也没有通过引用传递它,因此 main() 函数中的 b 将保持为零。你也可以使用类似

void exp(int& b)
{
    while(b==0) {
        std::cout << "Enter b again : ";
        std::cin >> b;
    }
}

请注意,这仍然存在缺陷,没有考虑用户输入错误的非数字输入的情况。

try-catch 很慢,因为它可以展开调用堆栈并且不适合作为流控制语句。 throw 可以在任何地方调用的任何函数中遇到,在 trycatch 之间的任何嵌套级别,但从 catch 返回将优雅地退出堆栈中所有函数的范围,然后将执行传递给 {{ 1}}。