繁体   English   中英

异常和 C 风格的字符串

[英]Exceptions & C-style strings

我有异常问题:

#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;
}

我想打印“除以 0”,但我得到:

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

Process returned 134 (0x86)

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

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

我想打印“DIVIDED BY 0”,但我得到:在抛出一个 'except' 实例后调用终止

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

你声称你不会抛出异常,但你在撒谎。 结果是在您实际抛出时调用 std::terminate。

这个问题实际上是双重的。 首先,正如@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. 不要创建异常类,除非它添加了一些特定的值(尽管value可能只是你想专门捕获某种类型的异常并以某种方式处理。)如果你想要一个更一般的异常,那么std::runtime_error或在这种情况下std::overflow_error将是不错的选择,并且都将std::string作为构造函数的参数,因此无需创建自己的异常类。

例如:

#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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM