C++笔记7.06

知识点5 C++类型转换

1 静态类型转换(static_cast) 不支持不相关

用于类层次结构中基类和派生类之间指针或引用的转换

进行上行转换:用基类指针、引用转向子类空间(安全)

进行下行转换:用子类指针指向父类(不安全)

  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. class Animal{};  
  6. class Dog:public Animal{};  
  7. class Other{};  
  8.   
  9. int main()  
  10. {  
  11.     //static_cast作用于基本类型  
  12.     char ch = 'a';  
  13.     double d = static_cast<double>(ch);  
  14.     cout << d <<endl;  
  15.     //static_cast作用于自定义数据类型(结构体、类)  
  16.     //上行转换 安全  
  17.     Animal *p = static_cast<Animal*> (new Dog);  
  18.     //下行转换 不安全 越界  
  19.     Dog *p1= static_cast<Dog *>(new Animal);  
  20.     //static_cast 不能作用于不相关的类之间的转换  
  21.     //Animal*p2 = static_cast<Animal*>(new Other);  
  22.   
  23.   
  24.     return 0;  
  25. }  

2 动态转换dynamic_cast 不支持基本类型 不支持不安全 不支持不相关

用于类层次的上行、下行转换

  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. class Animal{};  
  6. class Dog:public Animal{};  
  7. class Other{};  
  8.   
  9. int main()  
  10. {  
  11.     //dynamic_cast 不支持基本类型  
  12.     char ch = 'a';  
  13.     //double d = dynamic_cast<double>(ch);//err  
  14.     //dynamic_cast上行转换是安全的(父类指针指向子类空间)  
  15.     Animal *p1 = dynamic_cast<Animal*> (new Dog);  
  16.     //dynamic_cast下行转换不安全(子类指针转向父类空间)  
  17.     //Dog *p2 = dynamic_cast<Dog*> (new Animal);//err  
  18.     //dymanic_cast不支持没有关系的类型转换  
  19.     //Animal *p3 = dynamic_cast<Animal*> (new Other);//err  
  20.     return 0;  
  21. }  

3 常量转换const_cast 不支持非指针和引用转换

  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. class Animal{};  
  6. class Dog:public Animal{};  
  7. class Other{};  
  8.   
  9. int main()  
  10. {  
  11.     const int *p = NULL;  
  12.     int *p1 =const_cast<int*>(p);  
  13.   
  14.     int *p2 = NULL;  
  15.     const int *p3 = const_cast<const int *> (p2);  
  16.   
  17.     //const_cast 不支持非指针或者非引用的转换  
  18.     const int a = 100;  
  19.     //int b = const_cast<int>(a);//err  
  20.   
  21.     //常引用转换成普通引用  
  22.     int data = 100;  
  23.     const int &ob = data;  
  24.     int &ob2 = const_cast<int&>(ob);  
  25.     return 0;  
  26. }  

4 重新解释转换reinterpret_cast 不支持基本类型以外其他都支持

  1. #i#include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. class Animal{};  
  6. class Dog:public Animal{};  
  7. class Other{};  
  8.   
  9. int main()  
  10. {  
  11.     //reinterpret_cast 不支持基本数据类型  
  12.     char ch ='a';  
  13.     //double d = reinterpret_cast<double>(ch);//err  
  14.   
  15.     //reinterpret_cast 支持不相关类型间的转换  
  16.     Animal *p1 = reinterpret_cast<Animal *>(new Other);  
  17.   
  18.     //上行转换  
  19.     Animal *p2 = reinterpret_cast<Animal *>(new Dog);  
  20.   
  21.     //下行转换  
  22.     Dog *p3 = reinterpret_cast<Dog *>(new Animal);  
  23.     return 0;  
  24. }  

知识点6 异常的概述

常见的异常:除数为0溢出,数组下标越界,所需要读取的文件不存在,空指针,内存不足等等

C++如果抛出异常不捕获处理,程序直接崩溃退出

1、C语言通过返回值来判断程序运行状态容易忽略,也容易与正常返回结果混淆

2.C++抛出异常并捕获

抛出异常:thorw

捕获异常:try……catch

注意:异常机制和函数机制互不干涉,但是捕获方式是通过严格类型匹配的

  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. int myDiv(int a, int b)  
  6. {  
  7.     if(b == 0)  
  8.         throw 0;//抛出异常  
  9.     return a/b;  
  10.   
  11. }  
  12. int main()  
  13. {  
  14.     try{  
  15.         int ret = myDiv(10,0);  
  16.         cout << "ret = " << ret << endl;  
  17.     }  
  18.     catch(int e)//只捕获抛出int类型的异常  
  19.     {  
  20.         cout << "捕获到int类型异常 e = " << e << endl;  
  21.     }  
  22.   
  23.     catch(float e)//只捕获抛出float类型的异常  
  24.     {  
  25.         cout << "捕获到float类型异常 e = " << e << endl;  
  26.     }  
  27.   
  28.     catch(char e)//只捕获抛出char类型的异常  
  29.     {  
  30.         cout << "捕获到char类型异常 e = " << e << endl;  
  31.     }  
  32.   
  33.     catch (...)//捕获所有异常  
  34.     {  
  35.         cout << "捕获到其他异常" << endl;  
  36.     }  
  37.     return 0;  
  38. }  

知识点7 栈解旋

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

  1. #include <iostream>  
  2. #include <cstring>  
  3.   
  4. using namespace std;  
  5.   
  6. class Person  
  7. {  
  8. private:  
  9.     string name;  
  10. public:  
  11.     Person(string name)  
  12.     {  
  13.         this->name = name;  
  14.         cout << "Person" << name << "构造函数" << endl;  
  15.     }  
  16.   
  17.     ~Person()  
  18.     {  
  19.         cout << "Person" << name << "析构函数" << endl;  
  20.     }  
  21. };  
  22.   
  23. int main()  
  24. {  
  25.     try{  
  26.         Person ob1("1_阿尔贝尔");  
  27.         Person ob2("2_阿尔贝尔");  
  28.         Person ob3("3_阿尔贝尔");  
  29.         Person ob4("114514_阿尔贝尔");  
  30.   
  31.         throw 10;  
  32.     }  
  33.   
  34.     catch(int)  
  35.     {  
  36.         cout << "捕获到int异常" << endl;  
  37.     }  
  38.   
  39.     cout << "其他函数" << endl;  
  40.     return 0;  
  41. }  

知识点8 异常的接口声明

把要抛出的异常一一列举出来

为了加强函数的可读性,可以在函数声明中列出可能抛出的异常的所有类型。

如果一个函数抛出了它异常接口声明中所不允许抛出的异常,unexpected函数会被调用,该函数会默认调用terminate函数中断程序

  1. void fun() throw(int,char,char*)//只抛出int,char,char*异常  
  2. void fun() throw()//不抛出异常 

知识点9 异常的生命周期

  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. class MyException  
  6. {  
  7. public:  
  8.     MyException()  
  9.     {  
  10.         cout << "异常构造" << endl;  
  11.     }  
  12.   
  13.     MyException(const MyException &ob)  
  14.     {  
  15.         cout << "异常拷贝构造" << endl;  
  16.     }  
  17.     ~MyException()  
  18.     {  
  19.         cout << "异常析构" << endl;  
  20.     }  
  21. };  
  22.   
  23. int main()  
  24. {  
  25.     try{  
  26.     MyException ob;  
  27.         throw ob;  
  28.     }  
  29.   
  30.     catch(MyException)  
  31.     {  
  32.         cout << "捕获到MyException异常" << endl;  
  33.     }  
  34.   
  35.     cout << "其他函数" << endl;  
  36.     return 0;  
  37. }  

知识点10 标准异常

标准异常类的具体描述:

异常名称描述
exception所有标准异常类的父类
bad_alloc当operator new and operator new[],请求分配内存失败时
bad_exception这是个特殊的异常,如果函数的异常抛出列表里声明了bad_exception异常,当函数内部抛出了异常抛出列表中没有的异常,这是调用的unexpected函数中若抛出异常,不论什么类型,都会被替换为bad_exception类型
bad_typeid使用typeid操作符,操作一个NULL指针,而该指针是带有虚函数的类,这时抛出bad_typeid异常
bad_cast使用dynamic_cast转换引用失败的时候
ios_base::failureio操作过程出现错误
logic_error逻辑错误,可以在运行前检测的错误
runtime_error   运行时错误,仅在运行时才可以检测的错误

logic_error的子类:

异常名称描述
length_error试图生成一个超出该类型最大长度的对象时,例如vector的resize操作
domain_error参数的值域错误,主要用在数学函数中。例如使用一个负值调用只能操作非负数的函数
out_of_range超出有效范围  
invalid_argument参数不合适。在标准库中,当利用string对象构造bitset时,而string中的字符不是’0’或’1’的时候,抛出该异常

runtime_error的子类:

异常名称描述
range_error计算结果超出了有意义的值域范围
overflow_error算术计算上溢
underflow_error算术计算下溢
invalid_argument参数不合适。在标准库中,当利用string对象构造bitset时,而string中的字符不是’0’或’1’的时候,抛出该异常
  1. #include <iostream>  
  2. #include <exception>  
  3.   
  4. using namespace std;  
  5.   
  6. class Person  
  7. {  
  8. private:  
  9.     int age;  
  10. public:  
  11.     Person(int age)  
  12.     {  
  13.         if(age<0 || age>150)  
  14.             throw out_of_range(“age无效”);  
  15.         this->age = age;  
  16.     }  
  17. };  
  18.   
  19. int main()  
  20. {  
  21.     try{  
  22.     Person ob(200);  
  23.     }  
  24.   
  25.     catch(exception &e)  
  26.     {  
  27.         cout << “捕获到异常:” << e.what() <<endl;  
  28.     }  
  29.   
  30.     cout << “其他函数” << endl;  
  31.     return 0;  
  32. }  

知识点11 cin的拓展

1.cin.get获取一个字符 cin.getline获取带空格的字符串

  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. int main()  
  6. {  
  7.     //cin的基本用法  
  8.     int data = 0;  
  9.     cin >> data;  
  10.     cout << data << endl;  
  11.   
  12.     //获取一个字符  
  13.     char ch;  
  14.     cin >> ch;  
  15.     cout << “ch = ” << ch << endl;  
  16.   
  17.     //获取一个字符  
  18.     char ch1 = ‘\0’;  
  19.     ch1 = cin.get();//获取一个字符  
  20.     cout << “ch1 = ” << ch1 << endl;  
  21.   
  22.     //获取字符串  
  23.     char name[128] = “”;  
  24.     cin >> name;//遇到空格、回车自动结束  
  25.     cout << “name = ” << name << endl;  
  26.   
  27.     //获取一行  
  28.     char name2[128] = “”;  
  29.     cin.getline(name2,sizeof(name2));//可以获取带空格的字符串  
  30.     cout << “name2 = ” << name2 << endl;  
  31.     return 0;  
  32. }  

2.cin.ignore忽略缓冲区的前n个字符

  1. char name[128] = “”;  
  2. cin.ignore(2);//忽略前两个字节  
  3. cin >> name;  
  4. cout << “name = ” << name << endl;  

3.cin.putback放回缓冲区

  1. char ch = 0;  
  2. ch = cin.get();  
  3. cout << “ch = ” << ch << endl;  
  4.   
  5. cin.putback(ch);//将ch的字符放回缓冲区  
  6.   
  7. char name[32] = “”;  
  8. cin >>name;  
  9. cout << “name = ” << name << endl;  
  10. return 0;  

4.cin.peek偷窥

  1. char ch = 0;  
  2. ch = cin.peek();  
  3. cout << “偷窥缓冲区的数据为:” << ch << endl;  
  4.   
  5. char name[32] = “”;  
  6. cin >> name;  
  7. cout << “name = ” << name << endl;  
  8. return 0;  

发表评论

邮箱地址不会被公开。 必填项已用*标注