zoukankan      html  css  js  c++  java
  • C++异常处理

    一 C++异常处理机制

      异常处理基本思想:执行一个函数的过程中发现异常,可以不用再本函数内立即进行处理,而是抛出该异常,让函数的调用者直接或间接的处理这个问题。

      C++异常处理进制由三个模块组成:try、throw、catch

      try---catch基本语法:

    try 
     { 
    可能抛出异常的语句;(检查) 
    } 
    catch(类型名[形参名])//捕获特定类型的异常 
    { 
     //处理1; 
    } 
    catch(类型名[形参名])//捕获特定类型的异常 
    { 
     //处理2; 
    } 
    catch(…)//捕获所有类型的异常 
    { 
     } 

       示例:

    void f1(int i)
    {
        if (i<0)
            throw 1;
    }
    void f2()
    {
        f1(-45);
    }
    void f3()
    {
        f2();
    }
    void f4()
    {
        f3();
    }
    int main()
    {
        try{
            f4();
        }
        catch (int i)
        {
            cout <<"error code:"<< i <<"
    "<< endl;
        }
        system("pause");
        return 0;
    }

    二 异常捕获的匹配规则

      try块里面抛出哪种异常,则catch里面捕获哪种类型的异常,一般情况下,类型必须完全匹配,但以下三种情况可以进行类型转换:

      (1)运行从非const对象到const对象转换,即throw一个非const对象,catch一个const对象

      (2)运行从派生类类型到基类型的转换

      (3)将数组转换为数组类型的指针,函数转换为指向函数类型的指针

    #include <math.h>
    
    bool Equal(double num1, double num2)
    {
        if (num1 - num2 > -0.0000001 &&
            num1 - num2 < 0.0000001)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    
    // 基数为base为double类型,exponent为整数
    double Power(double base, int exponent) // throw(char *)
    {
        // 当底数为0且指数为负数时抛出异常
        if (Equal(base,0.0) && (exponent < 0))
        {
            throw exception("base must be positive!"); // thror "error"
        }
        double dbResult = 1.0;
        if (exponent >= 1)
        {
            for (int i = 0; i < exponent; i ++)
            {
                dbResult *= base;
            }
        }
        else if (exponent < 0)
        {
            for (int j = 0; j < abs(exponent); j ++)
            {
                dbResult *= base;
            }
            dbResult = 1/dbResult;
        }
        else if(exponent == 0)
        {
            dbResult = 1;
        }
        return dbResult;
    }
    
    void main()
    {
        clock_t start,end;
        start = clock();
        try
        {
            cout << Power(0,1) << endl;
            cout << Power(2, 3) << endl;
            cout << Power(-2, 3) << endl;
            cout << Power(2, -3) << endl;
            cout << Power(2, 0) << endl;
            cout << Power(0,-1) << endl;
        }
        catch (exception & e) // char *p
        {
            cout << e.what() << endl;  // cout << p << endl;
        }
        end = clock();
        cout << "程序运行时间:" << (double)(end - start) / CLOCKS_PER_SEC << endl;
        return;
    }

    三 异常规范

      (1)函数声明之后,列出函数可能抛出的异常类型,并保证该函数不会抛出其他类型的异常

        a. void fun() throw(toobig,toosmall,divzero); // 函数抛出指定异常

        b. void f();  // 这意味函数会抛出任何一种异常

        c. void f() throw();   // 这意味函数不会抛出异常

      (2) 保证不在构造函数中抛出异常,因为构造函数的作用是构造对象并初始化,一旦抛出异常,有可能导致对象不完整或没有完全初始化

      (3)保证不在析构函数中抛出异常,因为析构函数的作用是完成资源的清理,一旦抛出异常,有可能导致内存泄露等等

    四 使用异常的开销

      当异常被抛出时有相当的运行时间方面的开销,这就是从来不想把异常用于普通流控制的一部分的原因,而不管它多么令人心动。设计异常处理的重要目标之一是:在异常处理实现中,当异常不发生时应不影响运行速度,这就是说,只要不抛出异常,代码的允许速度如同没有加载异常处理一样,无论与否,异常处理都依赖于使用的特定编译器,异常处理会引出额外信息,这些信息被编译器置于栈上。

  • 相关阅读:
    二叉树序列化和反序列化
    js推箱子
    查找一个二叉树的后继节点
    采用非递归方式遍历二叉树
    采用递归方式遍历二叉树
    判断两个单向链表是否相交
    拷贝带随机指针的链表
    将单向链表按某值划分成左边小,中间相等,右边大的形式
    滑动窗口求最大值
    给定一个只包含字符’(’,’)’,’{’,’}’,’[‘和’]'的字符串,判断输入字符串是否有效
  • 原文地址:https://www.cnblogs.com/xiaobingqianrui/p/8855836.html
Copyright © 2011-2022 走看看