• C++基础知识(九)--- 类型转换 & 异常


    目录

    一. C++类型转换(了解)

    1. 静态转换

    2. 动态转换

    3. 常量转换

    4. 重新解释转换

    二. 异常

    1. C语言处理异常的方法:

    2. 异常的语法

    3. 异常的优势

    4. 异常的严格类型匹配

    5. 异常的接口说明

    6. 栈解旋(重点)

    7. 异常变量的生命周期

    (1)产生三个对象

    (2)产生两个对象

    (3)产生一个对象(常用)

    (4)注意

    8. 异常的多态

    9. C++标准异常库

    10. 仿照标准异常库写自己的异常类


    一. C++类型转换(了解)

    就是将一种数据类型转换成另一种数据类型。例如,如果将一个整型值赋给一个浮点类型的变量,编译器会暗地里将其转换成浮点类型。

    标准C++提供了一个显式的转换语法,来替代C风格的类型转换。

    C++风格的强制转换可以更好地控制转换过程。

    1. 静态转换

    (1)用于基本数据类型之间的转换。

    1. void test()
    2. {
    3. char a = 'a';
    4. double b = static_cast<double>(a);
    5. }

    (2)用于类层次结构中父类和子类之间指针或引用的转换。

    父类转子类是不安全的;子类转父类是安全的。

     

    2. 动态转换

    主要用于类层次间的上行转换和下行转换;

    基础类型不能使用动态转换;

    向上转时,dynamic_cast 和 static_cast 的效果是一样的;

    向下转时,dynamic_cast 具有类型检查的功能,比static_cast更安全;

    3. 常量转换

    用来修改类型的 const 属性;

    常量指针被转换成非常量指针,仍然指向原来的对象;

    常量引用被转换成非常量引用,仍然指向原来的对象;

    不能直接对非指针和非引用的变量使用const_cast操作符去直接移除它的const。

    1. void test()
    2. {
    3. const int* p = NULL;
    4. //const -> 非const
    5. int* newP = const_cast<int*>(p);
    6. //非const -> const
    7. int* q = NULL;
    8. const int* newQ = const_cast<const int*>(q);
    9. }

    4. 重新解释转换

    最不安全的转换。

    主要用于将一种数据类型从一种类型转换为另一种类型。

    可以将一个指针转换成一个整数,也可以将一个整数转换成一个指针。

    1. void test()
    2. {
    3. //int转换成指针
    4. int a = 1;
    5. int* p = reinterpret_cast<int *>(a);
    6. //也可以对没有继承关系的类之间进行转换
    7. Father* f = NULL;
    8. Other* o = reinterpret_cast(f);
    9. }

    二. 异常

    异常处理就是处理程序中的错误。所谓错误是指在程序运行过程中发生的一些异常事件(如:除0溢出、数组下标越界、所要读取的文件不存在、空指针、内存不足等)。

    1. C语言处理异常的方法:

    ① 使用整型的返回值标识错误;② 使用 error 宏去记录错误。

     缺陷:

    •  返回值意思不明确;
    • 返回值只有一个,只能返回一条信息;
    • 返回值可以忽略。

    C++的异常处理可以解决这些问题。

    2. 异常的语法

     

    3. 异常的优势

    • 若有异常则通过 throw 操作创建一个异常对象并抛出;
    • 将可能抛出异常的程序段放到 try 块之中;
    • 如果在 try 段执行期间没有引起异常,那么跟在 try 后面的 catch 语句就不会执行;
    • catch 语句会根据出现的先后顺序被检查,匹配的 catch 语句捕获并处理异常;
    • 如果匹配的 catch 处理未找到,则运行函数 terminate 将自动被调用,并终止程序;
    • 返回值只能返回一条信息,但是对象有成员函数,可以包含多条信息;

    C++的异常处理使得异常的引发和处理不必在一个函数中,这样底层的函数可以着重解决具体问题,而不必过多的考虑异常的处理。上层调用者可以在适当的位置设计对不同类型异常的处理。

    4. 异常的严格类型匹配

    1. int func(int a, int b)
    2. {
    3. if (b == 0)
    4. {
    5. throw 10; //抛出int类型的异常
    6. throw 'a'; //抛出char类型的异常
    7. throw "hello"; //抛出char*类型的异常
    8. string str="hahaha";
    9. throw str;
    10. }
    11. return a / b;
    12. }
    13. void test()
    14. {
    15. int a = 10;
    16. int b = 0;
    17. try
    18. {
    19. func(a, b);
    20. }
    21. catch (int)
    22. {
    23. cout << "接收一个int类型的异常" << endl;
    24. }
    25. catch (char)
    26. {
    27. cout << "接收一个char类型的异常" << endl;
    28. }
    29. catch (char*)
    30. {
    31. cout << "接收一个char*类型的异常" << endl;
    32. }
    33. catch (...)
    34. {
    35. cout << "接收其他类型的异常" << endl;
    36. }
    37. }

    5. 异常的接口说明

    1. void func() throw(int, char) //只允许抛出 int 或者 char 异常
    2. {
    3. throw 10;
    4. }

    6. 栈解旋(重点)

     运行结果如下,可以看出,进行了两次构造,只进行了一次析构,所以发生了栈解旋。

    1. Maker构造
    2. Maker拷贝构造
    3. Maker析构
    4. 接收一个Maker异常
    5. Maker析构

    7. 异常变量的生命周期

    使用上边的 Maker 类。

    (1)产生三个对象

    (2)产生两个对象

    (3)产生一个对象(常用)

     

    (4)注意

    8. 异常的多态

    1. //异常的基类
    2. class Father
    3. {
    4. public:
    5. virtual void printM()
    6. {}
    7. };
    8. //1.有继承
    9. class SonNULL :public Father
    10. {
    11. public:
    12. virtual void printM() //2.重写父类的虚函数
    13. {
    14. cout << "空指针异常" << endl;
    15. }
    16. };
    17. class SonOut :public Father
    18. {
    19. public:
    20. virtual void printM()
    21. {
    22. cout << "越位溢出" << endl;
    23. }
    24. };
    25. void func(int a, int b)
    26. {
    27. if (a == 0)
    28. {
    29. throw SonNULL();
    30. }
    31. if (b == 0)
    32. {
    33. throw SonOut();
    34. }
    35. }
    36. void test()
    37. {
    38. int a = 0;
    39. int b = 1;
    40. try
    41. {
    42. func(a,b);
    43. }
    44. catch(Father& f) //3.父类引用指向子类对象
    45. {
    46. f.printM();
    47. }
    48. }

    9. C++标准异常库

    10. 仿照标准异常库写自己的异常类

    1. class Myout_of_range :public exception
    2. {
    3. public:
    4. Myout_of_range (const char* errinfo)
    5. {
    6. //const char*转换为string
    7. this->m_info = string(errinfo);
    8. }
    9. Myout_of_range (const string errinfo)
    10. {
    11. this->m_info = errinfo;
    12. }
    13. const char* what() const
    14. {
    15. //把string转换成const char*
    16. return this->m_info.c_str();
    17. }
    18. public:
    19. string m_info;
    20. };
    21. class Maker
    22. {
    23. public:
    24. Maker(int age)
    25. {
    26. if (age < 0)
    27. {
    28. throw Myout_of_range ("自己的异常类,age is not correct");
    29. }
    30. else
    31. {
    32. this->age = age;
    33. }
    34. }
    35. public:
    36. int age;
    37. };
    38. void test()
    39. {
    40. try
    41. {
    42. Maker m(-1);
    43. }
    44. catch(Myout_of_range& my)
    45. {
    46. cout << my.what() << endl;
    47. }
    48. }

     

  • 相关阅读:
    linux常用的一些辅助命令
    网络基本概念
    Effective C++ 学习笔记 条款22 将成员变量声明为private
    Go 实战|使用 Wails 构建轻量级的桌面应用:仿微信登录界面 Demo
    SpringMVC【文件上传(原生方式上传、上传多文件、异步上传、跨服务器上传 ) 】(五)-全面详解(学习总结---从入门到深化)
    Elasticsearch 基于地理位置的搜索查询
    我们该如何提升测试效率?
    功能强大的流式文本编辑器 sed
    ksdbmerge.tools All Product Crack
    spring源码 - 理解@Import原理及运用
  • 原文地址:https://blog.csdn.net/woshizuopie/article/details/126006838