C++异常 - 抛出字符串

21

我对我的代码有一个小问题。不知何故,当我尝试使用以下代码抛出一个字符串时,在Visual Studio中会出现错误。

#include <string>
#include <iostream>
using namespace std;

int main()
{
    
    char input;

    cout << "\n\nWould you like to input? (y/n): ";
    cin >> input;
    input = tolower(input);

    try
    {
        if (input != 'y')
        {
            throw ("exception ! error");
        }
    }
    catch (string e)
    {
        cout << e << endl;
    }
}

错误:

error


1
如果你想捕获一个字符串,就抛出一个字符串而不是一个字符串字面量。否则,就捕获一个const char*。虽然使用其中一个异常类会是一个更好的主意。 - Andreas DM
3个回答

24

您目前抛出的是const char*而不是std::string,您应该抛出string("error")

编辑:错误已得到解决。

throw string("exception ! error");

是的,但它会抛出异常:throw ("异常!错误");这是一个字符串。 - Jimmy
@Jimmy 是的,它没有找到捕获 const char* 的情况。 - Syntactic Fructose
4
@SyntacticFructose - 这是很危险的(通过值抛出/捕获std :: string),因为必须构造字符串,这可能会引发错误。应该通过引用捕获字符串。 - PaulMcKenzie

23

抛出一个字符串确实是个坏主意。

在你的代码中,你抛出了一个 const char*。抛出内置类型(比如 intfloat,或者像这种情况下的 const char*)是个坏主意,因为这些内置类型没有提供适当的上下文错误信息。实际上,当捕获到异常时,理解异常的原因是很重要的,以便采取适当的措施。但是内置类型并不能提供此类信息,导致在捕获异常时难以理解异常的原因根本原因

此外,抛出内置类型也会令人困惑,因为这不是现代 C++ 的惯用方式。在 C++ 中,抛出异常的惯用方式是定义一个适当的 C++ 类来表示异常,通常从 std::exception 派生它,或者从其他派生自 std::exception 的类派生它,然后抛出该异常类的实例。
您还可以简单地抛出 C++ 标准库中已定义的一些异常类,比如 std::runtime_error。
例如,您可以抛出一个 std::runtime_error,将错误消息字符串传递给构造函数,像这样:
throw std::runtime_error("Your error message");

在捕获点,你可以通过常量引用(const &)捕获runtime_error异常,并调用what()方法获取错误字符串。
try {
    ...
} catch (const std::runtime_error& ex) {
    // Invoke ex.what() to get the error message
}

但是不要抛弃这个“裸露”的字符串。
如果你想定义一个自定义的异常类,你可以从std::runtime_error派生它,就像这样:
class YourCustomException
    : public std::runtime_error 
{
  public:

    YourCustomException(const char* message)
        : std::runtime_error(message) {
    }

    YourCustomException(const std::string& message)
        : std::runtime_error(message) {
    }
};

像这样扔出去:
throw YourCustomException("Your error message");

抓住它就像这样:
try {
    ...
} catch (const YourCustomException& ex) {
    // Invoke ex.what() to get the error message
}

2
我同意,抛出任何与std::exception无关的东西都是一个非常糟糕的主意... - MFH
2
甚至可以直接抛出 std::runtime_error('exception text') - user1084944
4
为什么?我感谢你的建议,但是背后的推理是什么? - feuGene
@feuGene 你可能想看一下这个C++ FAQ - Mr.C64
9
那个页面解释了为什么抛出std::runtime_exception的派生类是有用的,并建议“最好抛出对象,而不是内置类型”,但它仍然没有解释为什么抛出内置类型会有什么问题。 - feuGene
显示剩余2条评论

3
#include <string>
#include <iostream>
using namespace std;

int main()  
{
    
    char input;

    cout << "\n\nWould you like to input? (y/n): ";
    cin >> input;
    input = tolower(input);

    try
    {
        if (input != 'y')
        {
            throw std::runtime_error("Exception ! Error");
        }
    }

    catch(const std::exception& e)
    {
        std::cout << "Caught exception: " << e.what() << '\n';
    }
}

你的回答可以通过添加更多支持信息来改进。请[编辑]以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是否正确。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接