有没有更好的方法来处理异常? try-catch 块真的很难看

Is there a better way to handle exceptions ? try-catch block is really ugly

我读过 this and find out it's important to handle exceptions, i use nlohmann::json (from github) 几乎在我的大多数成员函数中都使用 nlohmann::json::parsenlohmann::json::dump,如果输入有问题,它们有机会抛出异常。

所以我需要处理像这样抛出异常的机会:

bool my_class::function(const std::string& input) const
try
{
    using namespace nlohmann;

    const auto result = json::parse(input);
    const auto name = result["name"].dump();

    /* and ... */
}
catch (const std::exception& e)
{
    /* handle exception */
}

但是我想知道哪一行代码抛出异常,所以如果我这样写:

bool my_class::function(const std::string& input) const
{
    using namespace nlohmann;

    try
    {
        const auto result = json::parse(input);
    }
    catch(const std::exception& e)
    {
        /* handle exception */
    }

    try
    {
        const auto name = result["name"].dump();
    }
    catch(const std::exception& e)
    {
        /* handle exception */
    }

    /* and ... */
}

它给我留下了数千个 try-catch 块。为什么要处理异常更好?

我会这样: 设置一个 "sequence pointer" 来记录 where/what 您是否正在尝试解析,例如带有模式的字符串 trying to parse a... 这样您就可以 know/notify json.

中错误元素的确切位置

查看下面的示例,如果 "name is faulty, then r is holding the value " 尝试解析名称”,那么在异常中,您将获得有关导致问题的 json 元素的信息:)

bool my_class::function(const std::string& input) const
{
    std::string r{""};
    try
    {
        using namespace nlohmann;
        r="trying to parse input";
        const auto result = json::parse(input);

        r="trying to parse name";
        const auto name = result["name"].dump();

        r="trying to parse age";
        const auto age = result["age"].dump();

        /* and ... */
    }
    catch (const std::exception& e)
    {
        /* handle exception */
    }
}

您可能已经注意到,C++ 没有可用的信息。 @ΦXocę웃Пepeúpaツ 提供了一些很好的解决方法。

让我提供一些其他观点,作为您程序的最终用户,我对程序失败的代码行不感兴趣。我提供的 JSON 要么正确,要么不正确。在第二种情况下,我想知道我需要做什么才能修复 JSON。查看 code 定义异常,这看起来非常详细。

你对它感兴趣的时刻是当你在你的程序中写了一个错误并且你得到了意想不到的错误。在那个时间点,您最好将调试器附加到您的程序并逐步执行它,同时在抛出任何异常时中断。这不仅会给你行号,还会给你堆栈上所有可用的信息...... 我可以建议对您的代码编写单元测试,这样您就可以调试一小段代码。理想情况下,如果您的程序中仍然遇到未发现的错误,您甚至可以将失败案例减少到新的单元测试。

最后,性能的争论。拥有更多细节需要收集更多细节。这种收集是有代价的。在其他编程语言中,例如 Java,您可以向异常请求调用堆栈,而在 C++ 中,异常是最低限度的。虽然跟踪行号可能不会那么昂贵,但它确实需要最终用户不需要的额外汇编指令。

简而言之,该语言没有提供获取行号的便捷方法。这是因为有更好的方法来获取此信息以及更多信息:您的调试器。