• C++ DAY08 异常


    概念

    异常事件(如:除 0 溢出,数组下标越界,所要读取的文件不存在 , 空指针,内存不足
    等等)
    在 C 语言对错误的处理是两种方法:
            一是使用整型的返回值标识错误;
            二是使用 errno 宏(可以简单的理解为一个全局整型变量)去记录错误。
    C++ 异常不可忽略 ( 如果忽略,进程结束 ) 。
    异常作为一个类,可以拥有自己的成员,这些成员就可以传递足够的信息。
    抛出异常 ----> 捕获异常。
    示例:
    1. int main(int argc, char *argv[])
    2. {
    3. int num = 10 / 0;
    4. cout << "OVER" << endl;
    5. return 0;
    6. }
    7. //不会显示OVER,程序异常结束

    抛出异常

    语法:throw 值或变量;

    例如:

            throw 0;
            throw 1.1;
            throw 'a';
            throw "abc";

    捕获异常

    语法:

    try{
            可能会产生异常的代码
            111
            222 出现异常
            333
    }
    catch( 数据类型 1 变量名 )
    {
            当throw 的值与数据类型 1 相同进入此处
    }
    catch( 数据类型 2 变量名 )
    {
            当throw 的值与数据类型 2 相同进入此处
    }
    ...
    catch(...)
    {
            当throw 的值以上数据类型都不相同进入此处
    }

    示例

    1. #include
    2. #include
    3. using namespace std;
    4. //异常步骤,抛出异常,捕获异常
    5. int mydiv(int a,int b)
    6. {
    7. if(b == 0)
    8. {
    9. // 抛出异常
    10. int num = 0;
    11. throw num;
    12. }
    13. return a / b;
    14. }
    15. void test01(){
    16. try{
    17. mydiv(10,0);
    18. }
    19. catch(int e)
    20. {
    21. cout << e << endl;
    22. }
    23. catch(char const* s)
    24. {
    25. cout << s << endl;
    26. }
    27. catch(...)
    28. {
    29. cout << "其他异常" << endl;
    30. }
    31. }
    32. int main(int argc, char *argv[])
    33. {
    34. test01();
    35. return 0;
    36. }

    栈解旋

    概念

            异常被抛出后,从进入 try 块起 , 到异常被抛掷前 , 这期间在栈上构造的所有对象 , 都会
    被自动析构。析构的顺序与构造的顺序相反 , 这一过程称为栈的解旋

    示例

    1. class A{
    2. private:
    3. int num;
    4. public:
    5. A(int num):num(num)
    6. {
    7. cout << "构造函数" << num << endl;
    8. }
    9. ~A()
    10. {
    11. cout << "析构函数" << num << endl;
    12. }
    13. };
    14. void test02()
    15. {
    16. A a1(1);
    17. A a2(2);
    18. throw 0;
    19. }
    20. int main(int argc, char *argv[])
    21. {
    22. try{
    23. test02();
    24. }
    25. catch(...)
    26. {
    27. }
    28. return 0;
    29. }

    结果

             构造函数1
            构造函数2
             析构函数2
             析构函数1

    异常的接口声明

    作用

            限定异常抛出的类型种类

    语法

            返回值类型 函数名( 形参列表 )throw( 数据类型 1, 数据类型 2,...)
            {
                    函数体
            }
            注意:
                    声明异常后,当前函数中只能抛出指定类型的异常
                    throw():不允许抛出任何异常

    示例

    1. void fun01()throw(int,char)
    2. {
    3. // throw 10;//可以
    4. // throw 'a';//可以
    5. // throw 3.14f;//不可以
    6. }
    7. void test03(){
    8. try{
    9. fun01();
    10. }
    11. catch(int)
    12. {
    13. cout << "int的异常" << endl;
    14. }
    15. catch(char)
    16. {
    17. cout << "char的异常" << endl;
    18. }
    19. catch(float)
    20. {
    21. cout << "float的异常" << endl;
    22. }
    23. }
    24. int main(int argc, char *argv[])
    25. {
    26. test03();
    27. return 0;
    28. }

    异常对象的生命周期

    示例1:抛出异常对象

    1. #include
    2. #include
    3. using namespace std;
    4. class B{
    5. private:
    6. int num;
    7. public:
    8. B(int num):num(num)
    9. {
    10. cout << "构造函数" << num << endl;
    11. }
    12. B(const B& b)
    13. {
    14. this->num = b.num;
    15. cout << "拷贝构造" << num << endl;
    16. }
    17. ~B()
    18. {
    19. cout << "析构函数" << num << endl;
    20. }
    21. };
    22. void fun02()
    23. {
    24. throw B(10);
    25. }
    26. void test04()
    27. {
    28. try
    29. {
    30. fun02();
    31. }
    32. catch(B b)
    33. {
    34. }
    35. }
    36. int main(int argc, char *argv[])
    37. {
    38. test04();
    39. cout << "OVER" << endl;
    40. return 0;
    41. }

    结果

    示例2:抛出异常对象指针

    1. #include
    2. #include
    3. using namespace std;
    4. class B{
    5. private:
    6. int num;
    7. public:
    8. B(int num):num(num)
    9. {
    10. cout << "构造函数" << num << endl;
    11. }
    12. B(const B& b)
    13. {
    14. this->num = b.num;
    15. cout << "拷贝构造" << num << endl;
    16. }
    17. ~B()
    18. {
    19. cout << "析构函数" << num << endl;
    20. }
    21. };
    22. void fun02()
    23. {
    24. throw new B(10);
    25. }
    26. void test04()
    27. {
    28. try{
    29. fun02();
    30. }
    31. catch(B *b)
    32. {
    33. }
    34. }
    35. int main(int argc, char *argv[])
    36. {
    37. test04();
    38. cout << "OVER" << endl;
    39. return 0;
    40. }

    结果:

    示例3:抛出异常对象引用

    1. #include
    2. #include
    3. using namespace std;
    4. class B{
    5. private:
    6. int num;
    7. public:
    8. B(int num):num(num)
    9. {
    10. cout << "构造函数" << num << endl;
    11. }
    12. B(const B& b)
    13. {
    14. this->num = b.num;
    15. cout << "拷贝构造" << num << endl;
    16. }
    17. ~B()
    18. {
    19. cout << "析构函数" << num << endl;
    20. }
    21. };
    22. void fun02()
    23. {
    24. throw B(10);
    25. }
    26. void test04()
    27. {
    28. try{
    29. fun02();
    30. }
    31. catch(B &b)
    32. {
    33. }
    34. }
    35. int main(int argc, char *argv[])
    36. {
    37. test04();
    38. cout << "OVER" << endl;
    39. return 0;
    40. }

    结果:

    异常的多态

    概念 :   子类异常对象可以被父类异常类型捕获
    示例1:
    1. class BaseException{};
    2. class MyException01:public BaseException{};
    3. class MyException02:public BaseException{};
    4. void test05()
    5. {
    6. try{
    7. throw MyException01();
    8. }
    9. catch(BaseException)
    10. {
    11. cout << "可以捕获子类异常" << endl;
    12. }
    13. }
    14. int main(int argc, char *argv[])
    15. {
    16. test05();
    17. return 0;
    18. }
    示例 2: 子类异常重写父类虚函数
    1. class BaseException{
    2. public:
    3. virtual void printMsg(){}
    4. };
    5. class NullException:public BaseException{
    6. public:
    7. virtual void printMsg(){
    8. cout << "空指针异常" << endl;
    9. }
    10. };
    11. class ArrOutException:public BaseException{
    12. public:
    13. virtual void printMsg(){
    14. cout << "数组下标越界异常" << endl;
    15. }
    16. };
    17. void test05()
    18. {
    19. try{
    20. throw NullException();
    21. }
    22. catch(BaseException &e)
    23. {
    24. e.printMsg();
    25. }
    26. }
    27. int main(int argc, char *argv[])
    28. {
    29. test05();
    30. return 0;
    31. }

    标准异常库

    简介

    标准库中也提供了很多的异常类,它们是通过类继承组织起来的。异常类继承层级 . 结构图
    所示

    标准异常使用

    1. void test06()
    2. {
    3. try{
    4. throw bad_alloc();
    5. }
    6. catch(exception &e)
    7. {
    8. cout << e.what() << endl;
    9. }
    10. }
    11. int main(int argc, char *argv[])
    12. {
    13. test06();
    14. return 0;
    15. }

    自定义异常

    步骤

            1,定义一个类
            2,继承与异常类
            3,重写 wait 方法

    示例

    1. class my_exception:public exception
    2. {
    3. private:
    4. char* msg;
    5. public:
    6. my_exception()
    7. {
    8. }
    9. my_exception(char* msg)
    10. {
    11. this->msg = msg;
    12. }
    13. const char *what()const noexcept
    14. {
    15. return msg;
    16. }
    17. };
    18. void test07()
    19. {
    20. try{
    21. throw my_exception("自定义异常");
    22. }
    23. catch(exception &e){
    24. cout << e.what() << endl;
    25. }
    26. }
    27. int main(int argc, char *argv[])
    28. {
    29. test07();
    30. return 0;
    31. }

  • 相关阅读:
    Windows和VMware中的Ubuntu互传文件
    Linux之Shell编程快速上手
    高效数据传输:Java通过绑定快速将数据导出至Excel
    模型分类model
    Power BI 傻瓜入门 6. 从动态数据源获取数据
    以太坊 layer2: optimism 源码学习(二) 提现原理
    神经网络的三种训练方法,神经网络训练速度
    【斗破年番】探班视频曝光,猜测美杜莎怀孕之事,魔改剧情
    某银行软件测试笔试题,满分一百你能得多少分?
    Java集中常见的排序
  • 原文地址:https://blog.csdn.net/aisheisadas/article/details/134556406