• C++异常


    #include <iostream>
    using namespace std;
    int divide(int a,int b){
        if(b)
            return a/b;
        else
            throw "b can't zero.";
    }
    int main(){
        int a,b;
        cin >> a >> b;
        try{
            cout << divide(a,b) << endl;
        }
        catch(const char *s){
            cout << s << endl;
        }
        return 0;
    }
    

      如果异常没有catch住的话,最终会导致程序调用abort(),异常终止。

      如果异常不是本函数产生的话,可以再将异常抛出。在这个例子中print可以没有catch。

    #include <iostream>
    using namespace std;
    int divide(int a,int b){
        if(b)
            return a/b;
        else
            throw "b can't zero.";
    }
    void print(int result)
    {
    try{
        cout << result << endl;
        }
    catch(const char *s){
        throw;
        }
    }
    int main(){
        int a,b;
        cin >> a >> b;
    try{
        print(divide(a,b));
    }
    catch(const char *s){
        cout << s << endl;
    }
        return 0;
    }
    

      引发异常时,编译器总会自动创建一个临时拷贝,即使异常catch块中指定的是引用。因为f()异常,导致桟解退,a已经被析构了。

    class problem{//...};
    void f()
    {
        if(//...){
            problem a;
            thow a;
        }
        //...
    }
    int main()
    {
        try{
            f();
        }
        catch(problem &b){
            //.....
        }
        return 0;
    }
    

      可以利用类的关系来接异常

    class bad_1{};
    class bad_2:public bad_1{};
    class bad_3:public bad_2{};
    void f()
    {
        if()
            throw bad_1();
        else if()
            throw bad_2();
        else if()
            throw bad_3();
        //....
    }
    int main(){
        try{
            f();
        }
        catch(bad_3 &a){
    
        }
        catch(bad_2 &b){
    
        }
        catch(bad_3 &c){
    
        }
    }
    

      如果不知道异常的类型,可以用cathc(...){}来接住任何异常。

    异常规范和C++

    void f() throw(int,double){}
    

      这是C++98的新特性,但是C++11却摒弃了,不过还是支持它。表明f()可能会抛出int和double的异常,并保证该函数不会抛出任何其他类型的异常。让编译器添加执行运行阶段检查的代码,检查是否违背了异常规范。如果在运行时,函数抛出了一个没有被列在它的异常规范中的异常时(并且函数中所抛出的异常,没有在该函数内部处理)则系统调用C++标准库中定义的函数unexpected()。仅当函数中所抛出的异常,没有在该函数内部处理,而是逆调用链回溯寻找匹配的catch子句的时候,异常规范才起作用。如果异常规范形式为throw(),则表示不得抛出任何异常。

    void f() noexcept;//表明f()不会引发任何异常
    

    桟解退(unwinding the stack)

    exception类

    异常的基类

    //c++11
    class exception {
    public:
      exception () noexcept;
      exception (const exception&) noexcept;
      exception& operator= (const exception&) noexcept;
      virtual ~exception();
      virtual const char* what() const noexcept;
    }
    

      C++ 提供了一系列标准的异常,定义在 中,我们可以在程序中使用这些标准的异常。它们是以父子类层次结构组织起来的,如下所示:

    下表是对上面层次结构中出现的每个异常的说明:

    异常异常 描述
    std::exception 该异常是所有标准 C++ 异常的父类。
    std::bad_alloc 该异常可以通过 new 抛出。
    std::bad_cast 该异常可以通过 dynamic_cast 抛出。
    std::bad_exception 这在处理 C++ 程序中无法预期的异常时非常有用。
    std::bad_typeid 该异常可以通过 typeid 抛出。
    std::logic_error 理论上可以通过读取代码来检测到的异常。
    std::domain_error 当使用了一个无效的数学域时,会抛出该异常。
    std::invalid_argument 当使用了无效的参数时,会抛出该异常。
    std::length_error 当创建了太长的 std::string 时,会抛出该异常。
    std::out_of_range 该异常可以通过方法抛出,例如 std::vector 和 std::bitset<>::operator
    std::runtime_error 理论上不可以通过读取代码来检测到的异常。
    std::overflow_error 当发生数学上溢时,会抛出该异常。
    std::range_error 当尝试存储超出范围的值时,会抛出该异常。
    std::underflow_error 当发生数学下溢时,会抛出该异常。

    异常终止函数设置

    当异常没有接住时,程序自动调用terminate函数,而terminate默认调用abort函数,可以通过set_terminate来修改这个默认值。

    typedef void (*terminate_handler)();
    terminate_handler set_terminate(terminate_handler f) noexcept//c++11
    void terminater() noexcept;
    

      如果在异常规范中引发了规范中没有的异常,程序将调用unexpected函数,unexpected默认调用terminate,并最总导致abort函数的调用。可以通过set_unexpected来修改这个默认值。

    typedef void (*unexpected_handler)();
    unexpected_handler set_unexpected(unexpected_handler f) noexcept//c++11
    void set_unexpected() noexcept;
    
  • 相关阅读:
    LinkageSel无限级联动下拉菜单
    纯CSS+HTML自定义checkbox效果[转]
    jquery1.9+,jquery1.10+ 为什么不支持live方法了?
    电脑按键混乱,好像被锁定了Alt键
    docker 清理无用的卷
    dotnet core linux 接入支付宝H5支付,提示:System.PlatformNotSupportedException","Message":"'CspParameters' requires Windows Cryptographic API (CAPI), which is not available on this platform.
    【每天学一点Linux】centos7 docker 启动cpu100% 飙升居高不下 无法关机 无法杀死进程
    【每天学一点Linux】centos7修改selinux导致无法开机 Failed to load SELinux policy. Freezing
    webapi HttpGet标签
    强制结束虚拟机 centos home 卷丢失导致无法挂载进入 emergency mode 紧急模式
  • 原文地址:https://www.cnblogs.com/h-hg/p/8797527.html
Copyright © 2020-2023  润新知