• c++类型转换和异常


    c++类型转换

    知识点1 静态类型转换(static_cast)

    用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换
    进行上行转换:用父类指针、引用指向子类空间(安全)
    进行下行转换:用子类指针、引用指向父类空间(不安全)
    在这里插入图片描述

    #include 
    using namespace std;
    
    class Animal{
    public:
        virtual void showData(){
            cout << "父类函数" << endl;
        }
    };
    
    class Cat: public Animal{
    public:
        void showData(){
            cout << "子类函数" << endl;
        }
    };
    
    class Other{};
    
    void test01(){
        //static_cast 作用于 基本类型
        char ch = 'a';
        double d = static_cast<double>(ch);
        cout<<"d = "<<d<<endl;
    
        //static_cast 作用于 自定义数据类型(结构体 类)
        //关系的类之间
        //上行转换 安全
        Animal *p1 = static_cast<Animal*>(new Cat());
        p1->showData();
    
        //下行转换 不全 容易越界
        Cat *p2 = static_cast<Cat*>(new Animal);
        p2->showData();
        
        // static_cast 不能作用域 不相关的类之间转换
        //Animal *p3 = static_cast(new Other);//err
    }
    int main(int argc, char *argv[])
    {
        test01();
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    运行结果:
    在这里插入图片描述

    知识点2【动态转换dynamaic_cast】

    #include 
    
    using namespace std;
    
    class Animal{
    };
    
    class Cat: public Animal{
    public:
        void showData(){
            cout << "子类函数" << endl;
        }
    };
    
    class Other{};
    
    void test02(){
        //static_cast 不支持基本类型
        char ch = 'a';
        //double d = dynamic_cast(ch);//err
    
    
        //dynamic_cast 作用于 自定义数据类型(结构体 类)
        //关系的类之间
        //上行转换 安全
        Animal *p1 = dynamic_cast<Animal*>(new Cat());
        //dynamic_cast 下行转换 不全 容易越界
        //Cat *p2 = dynamic_cast(new Animal());//dynamic_cast不支持 不安全 的转换
        
    
        // dynamic_cast 不能作用域 不相关的类之间转换
        //Animal *p3 = static_cast(new Other);//err
    }
    
    int main(int argc, char *argv[])
    {
        test02();
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    知识点3【常量转换const_cast】

    //常量转换const_cast
    void test03(){
    
        const int *p1 = new int(10);
        int *p2 = const_cast<int*>(p1);
    
        int *p3 = new int(20);
        const int *p4 = const_cast<const int *>(p3);
    
        //const_cast不支持非指针或引用的转换
        const int a = 100;
        //int b = const_cast(a);//err
    
        int data = 100;
        //普通引用转换成常量引用
        int &data1 = data;
        const int &data2 = const_cast<const int &>(data1);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    知识点4【重新解释转换reinterpret_cast】

    
    #include 
    using namespace std;
    
    class Animal{
    public:
        virtual void showData(){
            cout << "父类函数" << endl;
        }
    };
    
    class Cat: public Animal{
    public:
        void showData(){
            cout << "子类函数" << endl;
        }
    };
    
    class Other{};
    
    
    void test04(){
    	
    	//reinterpret_cast 不支持基本数据类型
    	char ch='a';
    	//double d = reinterpret_cast(ch);//err
    
    	//reinterpret_cast 支持 不相关的类型间转换
    	Animal *p1 = reinterpret_cast<Animal *>(new Other);
    
    	//上行转换
    	Animal *p2 = reinterpret_cast<Animal *>(new Cat());
    
    	//下行转换
    	Dog *p3 = reinterpret_cast<Cat *>(new Animal());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    c++异常

    知识点1【异常的概述】

    常见的异常:除0溢出,数组下标越界,所要读取的文件不存在,空指针,内存不足等等。
    c++的异常一旦抛出 如果不捕获 该异常 程序直接退出。
    1、C语言通过返回值 来判断 第一:容易忽略 第二:容易和正常的结果混淆

    int myDiv(int a, int b){
        if(b == 0){
            return -1;
        }
        return a/b;
    }
    
    int main(int argc, char *argv[])
    {
        int ret = myDiv(10,-10);
        if(ret == -1){
            cout << "程序异常" << endl;
        }else{
            cout << "程序正常" << endl;
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    运行结果:
    在这里插入图片描述
    2、c++抛出异常 并捕获
    抛出异常:throw
    捕获异常:try…catch

    #include 
    #include
    using namespace std;
    
    int myDiv(int a,int b)
    {
        if(b == 0)
            return -1;//-1表示失败
        return a/b;
    }
    
    int myDiv01(int a,int b)
    {
        if(b==0)
            throw 0;//抛出异常
    
        return a/b;
    }
    
    void test02()
    {
        try{
            int ret = myDiv01(10,0);
            cout<<"ret = "<<ret<<endl;
        }
    #if 1
        catch(int e)//只捕获 抛出是int类型的异常
        {
            cout<<"捕获到int类型异常 e = "<<e<<endl;
        }
    #endif
        catch(float e)//只捕获 抛出是float类型的异常
        {
            cout<<"捕获到float类型异常 e = "<<e<<endl;
        }
        catch(char e)//只捕获 抛出是char类型的异常
        {
            cout<<"捕获到char类型异常 e = "<<e<<endl;
        }
    #if 0
        catch(...)
        {
            cout<<"捕获到其他异常"<<endl;
        }
    #endif
    
        cout<<"程序做其他事情"<<endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    运行结果:
    在这里插入图片描述

    知识点2【栈解旋(unwinding)】

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

    #include 
    #include
    using namespace std;
    
    class Person{
    private:
        string name;
    public:
        Person(string name)
        {
            this->name = name;
            cout<<"Person "<<name<<"构造函数"<<endl;
        }
        ~Person()
        {
            cout<<"Person "<<name<<"析构函数"<<endl;
        }
    };
    
    void test03()
    {
        try{
    
            Person ob1("00_德玛");
            Person ob2("01_小炮");
            Person ob3("02_小法");
            Person ob4("03_提莫");
    
            throw 10;
        }
        catch(int)
        {
            cout<<"捕获到int异常"<<endl;
        }
        cout<<"其他工作"<<endl;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    运行结果:
    在这里插入图片描述

    知识点3【异常接口声明】

    #include 
    #include
    using namespace std;
    
    void testFunc01()
    {
        //函数内部可以抛出任何异常
        //throw 10;
        //throw 4.3f;
        //throw 'a';
        //throw "hehe";
        string ob="heihie";
        throw ob;
    }
    
    //只能抛出int char 异常
    void testFunc02() throw(int,char)
    {
        throw 3.14f;
    }
    
    //函数 不抛出任何异常
    void testFunc03()throw()
    {
        throw 10;//外部捕获 不到
    }
    
    void test04()
    {
        try{
            testFunc03();
        }
        catch(int e)//只捕获 抛出是int类型的异常
        {
            cout<<"捕获到int类型异常 e = "<<e<<endl;
        }
        catch(float e)//只捕获 抛出是float类型的异常
        {
            cout<<"捕获到float类型异常 e = "<<e<<endl;
        }
        catch(char e)//只捕获 抛出是char类型的异常
        {
            cout<<"捕获到char类型异常 e = "<<e<<endl;
        }
        catch(char const *e)//只捕获 抛出是char *类型的异常
        {
            cout<<"捕获到char const *类型异常 e = "<<e<<endl;
        }
        catch(string e)
        {
            cout<<"捕获到string类型异常 e = "<<e<<endl;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    知识点4【异常的生命周期】

    在这里插入图片描述
    在这里插入图片描述
    推荐这种方式:
    在这里插入图片描述

    知识点5【标准异常】

    知识点6【cin的拓展】

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

    #include 
    #include
    using namespace std;
    
    void test07(){
        int data = 0;
        cin >> data;
        cout << "data = " << data << endl;
    
        char ch;
        cin >> ch;
        cout << "ch = " << ch << endl;
    
        //获取一个字符
        char ch1 = 'd';
        ch1 = cin.get();
        cout<<"ch1 = "<<ch1<<endl;
    
        char name[128]="ddddd";
        cin>>name;//遇到空格 回车结束获取
        cout<<"name="<<name<<endl;
    
        char name2[128]="sss";
        cin.getline(name2,sizeof(name));//可以获取带空格的字符串
        cout<<"name = "<<name2<<endl;
    
    }
    
    int main(int argc, char *argv[])
    {
        test07();
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    2、cin.ignore忽略 缓冲区的前 n个字符
    在这里插入图片描述
    3、cin.putback放回缓冲区
    在这里插入图片描述
    4、cin.peek偷窥
    在这里插入图片描述

  • 相关阅读:
    C++ 初识STL
    什么是句柄、什么是自上而下、自下而上分析—编译原理
    Sam Altman的成功学|升维指南
    MySQL 教程 1.1
    ElementUI浅尝辄止32:NavMenu 导航菜单
    LeetCode 1700. 无法吃午餐的学生数量:真假模拟(极简代码) + 奇技淫巧
    lodash学习
    RUST 和 GO 如何管理它们的内存
    四川思维跳动商务信息咨询有限公司可靠吗?
    火车票管理系统c++
  • 原文地址:https://blog.csdn.net/DUANJIAWEIDUANJIAWEI/article/details/126842052