C++ 异常 - 抛出 c 字符串作为异常不好吗?

问题描述 投票:0回答:8

我正在开发一个小型 C++ 程序并学习异常。下面的代码是否“不好”?如果是,我能做些什么来改进它?

try {
    // code
    if (some error) {
        throw "Description of error.";
    }
}
catch (char* errorMessage) {
    cerr << errorMessage << endl << "Fatal error";
}

抛出

char
数组作为异常有什么问题吗?

编辑: 这是更好的方法吗?

const char errorMessage[] = "Description of error";

try {
    // code
    if (some error) {
        throw errorMessage;
    }
}
catch (char* errorMessage) {
   cerr << errorMessage << endl << "Fatal error";
}
c++ exception
8个回答
54
投票

抛出一个标准异常对象要好得多。一般来说,最佳实践是抛出从

std::exception
派生的内容,这样,如果在某些情况下它确实导致程序终止,则实现有更好的机会打印有用的诊断信息。

因为做到这一点并不难,所以我永远不会建议抛出原始字符串文字。

#include <stdexcept>

void someFunction()
{
    try {
        // code
        if (some error) {
            throw std::runtime_error( "Description of error." );
        }
    }
    catch (const std::exception& ex) {
        std::cerr << ex.what() << "\nFatal error" << std::endl;
    }
}

11
投票

抛出字符串文字通常是一个坏主意,因为随着代码的发展,程序员可能需要用更多信息来丰富错误消息,例如变量的值,或抛出异常的行号。

鉴于未知的客户端代码正在捕获

const char*

,鼓励程序员使用更动态的机制来连接所需的信息:

    a
  • std::string
    +
    
    
  • a
  • std::ostringstream
    
    
  • 一个字符缓冲区,也许还有
  • strcat
     和/或 
    sprintf()
    
    
最明显的使用这些方法不起作用或效果不佳:

// temporaries... throw (std::string("couldn't parse input: ") + input).c_str(); throw (static_cast<std::ostringstream&&>(std::ostringstream() << "error line " << __LINE__)).str().c_str(); char buf[1024]; sprintf(buf, "error line %ld%", __LINE); throw buf; // not thread-safe static char buf...
即使程序员知道不要执行任何这些操作,他们仍然有合适的时间找到需要开始接受更丰富的值类型的所有客户端代码,特别是如果 

throw 的其他

catch
/
const char*
用法
 坚持。

因此,使用嵌入灵活的

std::string

描述
按值的类对于编写可维护的代码非常重要。


4
投票
不,抛出

char

 数组有问题。只是你应该收到,

catch(const char* const errorMessage) {...}

第一个

const

 是添加接收任何 
char
 数组的能力 
char*
 
const char*
 
char[]
 
const char[]


2nd

const

 是指定 
errorMessage
 不打算在 
catch
 块内更改


1
投票
存在一个普遍问题,即无法轻松过滤异常并根据类型对其采取行动。但是,我不知道是否有 C++ 特定原因不这样做


1
投票
std::exception(或者至少,std::runtime_error)包含一个字符串,可以通过what()方法访问。您能做的最好的事情就是使用它,因为它是标准的,并且其他代码可以期待它,并且因为它无论如何都能满足您的目的。

在这种情况下最好遵守标准。


0
投票
如果您将字符串作为错误抛出的想法是为了方便向用户显示错误,请考虑这会使本地化您的应用程序变得更加困难(尽管您可能会或可能不会担心)。

此外,如果应用程序的另一部分需要了解错误是什么,以便对其做出反应(例如,如果是断开连接错误,请尝试自动重新连接,但如果是密码错误,则只需向用户显示错误消息) ,最好有某种类型的错误代码可供异常捕获器使用。

在我们的应用程序中,我们的异常源自 std::exception。 它们包含错误类型(枚举)、调试错误消息(包括文件/行号)和本地化错误字符串。


0
投票
我认为这要简单得多。 :)。

#include <iostream> #include <exception> using namespace std; int main() { try { throw runtime_error("This is an Error"); }catch (exception& e){ cout << "Exception: " << e.what() << endl; } return 0; }
    

0
投票
另一个没有提到的方面:如果异常未被捕获并且程序终止,会向用户显示什么?在您的示例中,异常被捕获并处理。但这又如何呢?

int main() { throw "exception message!"; return 0; }
在我的机器上,运行此输出

terminate called after throwing an instance of 'char const*'

,这非常没有帮助 - 我看不到消息是什么!

相反,

throw std::runtime_error("exception message!");
产生

的输出

terminate called after throwing an instance of 'std::runtime_error' what(): exception message!
    
© www.soinside.com 2019 - 2024. All rights reserved.