例外& C风格的字符串

时间:2017-12-28 18:06:26

标签: c++ exception

我遇到异常问题:

#include <iostream>
#include <cstring>
#include <exception>

class except :public std::exception
{
    char* err;
public:
    except(const char* s) noexcept
    {
        err = new char[strlen(s) + 1];
        strcpy(err, s);
        err[strlen(s)] = 0; //is it necessary??
    }
    virtual const char* what() noexcept
    {return err;}
    virtual ~except() noexcept
    {delete err;}
};

double div(const double& a, const double& b) noexcept
{
    if (b == 0.0)
        throw except("DIVIDED BY 0");
    return a / b;
}

int main()
{
    try
    {
        std::cout << div(5.0, 0.0);
    }
    catch (std::exception &ex)
    {
        std::cout << ex.what();
    }
    return 0;
}

我想打印“DIVIDED BY 0”,但我得到了:

terminate called after throwing an instance of 'except'
  what():  std::exception
Aborted

Process returned 134 (0x86)

我应该将noexcept放在每个不抛出任何异常的函数/成员函数中吗?

err[strlen(s)] = 0是否必要? (在except :: except(const char * s)中)

2 个答案:

答案 0 :(得分:2)

I want to print "DIVIDED BY 0" but I get: terminate called after throwing an instance of 'except'

double div(const double& a, const double& b) noexcept

You are claiming that you won’t throw an exception, but you are lying. The result is the call to std::terminate when you actually throw.

答案 1 :(得分:2)

问题实际上是双重的。首先,正如@ manni66建议的那样,div不应该被声明为noexcept,这确实会导致运行时错误,但删除它并不能解决问题。

第二个问题是what已被宣布:

virtual const char* what() noexcept;

虽然它在std::exception中声明为:

virtual const char* what() const noexcept;

并且签名的这种差异意味着当它被std::exception的处理程序捕获时,它会调用std::exception::what()而不是except::what()

值得一提的几点:

  1. 确保您的函数重载与基类中的函数完全匹配。
  2. 如果您希望抛出某种类型的异常,那么请尝试使用特定处理程序捕获该异常,并为了清楚起见使用适当的名称作为异常。
  3. 正如其他人所说,如果可以,请尝试使用std::string课程。它将使事情变得更容易和更安全。虽然在这种情况下,正如第二点所述,字符串成员并不是真正必要的,因为该类具体到足以不需要进一步的限定。
  4. 不要创建一个异常类,除非它添加一些特定的值(虽然,可能只是你想要专门捕获某种类型的异常并处理以某种方式。)如果你想要一个更一般的例外,那么std::runtime_error或者在这种情况下std::overflow_error将是不错的选择,并且都将std::string作为构造函数的参数,所以没有需要创建自己的异常类。
  5. 例如:

    #include <exception>
    using namespace std;
    
    
    class divide_by_zero : public std::exception
    {
    public:
        virtual const char* what() const noexcept { return "DIVIDED BY 0"; }
    };
    
    double div(const double& a, const double& b)
    {
        if (b == 0.0)
            throw divide_by_zero();
        return a / b;
    }
    
    int main()
    {
        try
        {
            std::cout << div(5.0, 0.0);
        }
        catch (divide_by_zero &ex)
        {
            std::cout << ex.what();
        }
        catch (std::exception &ex)
        {
            std::cout << ex.what();
        }
        return 0;
    }
    

    <强>输出:

    DIVIDED BY 0