zoukankan      html  css  js  c++  java
  • 异常

    异常

    知道c++异常是怎么抛出的,我们怎么接受处理,及其过程

    一、异常

    1、什么是异常

    1.异常是程序在执行期间产生的问题。c++的异常指的是程序在运行的时候所发生的一些特殊的情况。比如除法运算,除以0的操作

    注意:我们平时看到的错误是语法错误

    二、c++异常

    1、c++异常的三个关键字

    1.throw:用throw抛出异常

    2.catch:用catch接受异常

    3.try:在try中执行写有抛出异常的代码

    2、示例

    try
    {
        throw "我是一个异常";
        cout<<"我是异常的下一句话"<<endl;
    }
    catch(const char* p)
    {
        cout<<"出了异常"<<endl;
        cout<<p<<endl;
    }
    
    #include<iostream>
    #include<windows.h>
    using namespace std;
    int fun(int a, int b)
    {
    	if (b == 0)
    		throw "除数不能为0";
    	return a / b;
    }
    //抛出的异常,和接收异常的地方类型要严格匹配,对于基本数据类型之间不会自动转换了
    int main()
    {
    	try
    	{
    		//有抛出异常的代码
    		fun(2, 0);
    	}
    	catch (const char* p)//将除数不能为0赋值给了p这个指针
    	{
    		//接收异常之后要做的事
    		MessageBox(0, p, 0, 0);
    	}
    	system("pause");
    	return 0;
    
    }
    

    注意:对于我们抛出的一个异常,我们必须接收,如果不接收就会报错,异常也可以嵌套,那么就会出现里层抛出一个异常,但是并没有在里层的catch块接收,那么外层如果有可以接收的,就会在外层接收

    //有点像套娃
    #include<iostream>
    #include<windows.h>
    using namespace std;
    int fun(int a, int b)
    {
    	if (b == 0)
    		throw "where";
    	return a / b;
    }
    //抛出的异常,和接收异常的地方,类型要严格匹配
    void test()
    {
    	try
    	{
    		//有抛出异常的代码
    		fun(2, 0);
    	}
    	catch (const char* p)//将除数不能为0赋值给了p这个指针
    	{
    		cout << p << endl;
    		throw 666.666;
    		//接收异常之后要做的事
    		//MessageBox(0, p, 0, 0);
    	}
    }
    void test1()
    {
    	try
    	{
    		test();
    	}
    	catch (double a)
    	{
    		cout << a << endl;
    		//cout << "我接住了异常1" << endl;
    		throw "我不接这个锅";
    	}
    	
    }
    int main()
    {
    	try
    	{
    		test1();
    	}
    	catch (const char* p)
    	{
    		cout << p << endl;
    	}
        
        catch(...)//可以接收任何异常(基本数据类型,但是像系统的异常接收不了)
        {
            cout<<"我接住了异常"<<endl;
        }
    	system("pause");
    	return 0;
    
    }
    

    3、异常的生命周期

    1.如果说抛出的异常是一个变量,那么这个变量的存活周期会从throw抛出异常开始直到接收这个异常,在这个过程中,这个变量都会存活

    4、栈解旋(了解)---一种现象

    1.从try开始,到throw抛出异常之前,所有栈上的对象会被释放,这个过程被称之为:栈解旋

    #include<iostream>
    #include<windows.h>
    using namespace std;
    class person
    {
    public:
    	person()
    	{
    		cout << "构造" << endl;
    	}
    	~person()
    	{
    		cout << "析构" << endl;
    	}
    };
    int fun(int a, int b)
    {
    	if (b == 0)
    	{
    		person p1;
    		person p2;
    		person p3;
    		throw p3;
    	}
    	return a / b;
    }
    int main()
    {
    	try
    	{
    		fun(1, 0);
    	}
    	catch(person& p)
    	{
    		cout << "接收到了异常" << endl;
    	}
        /*
        构造
    	构造
    	构造
    	析构
    	析构
    	析构
    	接收到了异常
    	析构
    	*/
    	system("pause");
    	return 0;
    
    }
    

    5、自定义异常

    下面是c++的一系列标准的异常,定义中我们是可以直接使用这些类的

    异常

    异常描述

    系统异常类的使用

    #include<iostream>
    #include<exception>
    #include<string>
    using namespace std;
    //自己写的异常类
    class myexception :public exception
    {
    	string str;
    public:
    	myexception(string str)
    	{
    		this->str = str;
    	}
    	const char* what()const
    	{
    		return str.c_str();
    	}
    };
    
    //异常多态的使用,还是父类指针指向子类对象,通过父类指针调用虚函数成员
    int main()
    {
    	//系统的异常类都是带参构造
    	//out_of_range oor("我是一个字符串");
    	myexception me("我也是一个字符串");
    	try
    	{
    		//throw oor;
    		throw me;
    	}
    	catch (exception&e)
    	{
    		cout << e.what() << endl;
    	}
    
    
    	system("pause");
    	return 0;
    
    }
    

    三、c++11

    1、初始化列表的方式

    //旧写法
    int a;
    int b(2.1);//将2赋值给b,但是小数点后的被省掉了 
    //新写法
    int m{4};
    int n={(int)3.14};//新的写法不允许有精度的损失
    

    2、空指针

    int* p=NULL;//旧写法
    int* p1=nullptr;//新写法
    

    3、自动类型

    int a=1;//旧写法
    auto b=2;//新写法,根据值去自动匹配b的类型,必须初始化
    auto i={1,2,3};
    
    //typeid(变量名).name()  返回变量的类型
    cout<<typeid(b),name()<<endl;//int
    
    
    //用来遍历数组,遍历有效内容,只是遍历
    int arr[]={1,2,3,5,6,8,6,5};
    for(auto i:arr)
    {
        cout<<i<<" ";
    }
    

    4、decltype()

    int a=1;
    decltype(a)b;//理解为根据a的类型定义了一个和a类型一致的b变量
    decltype((a))m=a;//再加一个圆括号,给a定义了一个别名m
    

    5、新的for规则

    string str="awdwdwf";
    //遍历这个str
    //旧方法
    for(int i=0;i<str.size();i++)
    {
        cout<<str[i]<<endl;
    }
    //新方法
    for(auto i:str)//这里其实使用的是迭代器输出
    {
        cout<<i<<endl;
    }
    //这个方法,只能用来遍历数组,容器,i所代表的是里面存的元素,如果是个指针,那么是不能这样遍历的
    

    6、给类型取别名

    typedef int hp;//旧写法
    using hp=int;//新写法
    
    typedef void (*pfun)();//旧写法
    using pfun=void(*)();//新写法
    

    7、default在类中的写法

    class A
    {
        public:
        A();
    }
    A::A()=default;//默认调用默认构造
    

    8、final禁止虚函数发生重写

    class A
    {
        public:
        virtual void fun()final{}
        //意味着这个虚函数,不能被子类重写,也就是说子类必须用父类的虚函数,所以父类的这个虚函数必须实现其功能
    }
    
  • 相关阅读:
    JavaStript基础 —— JavaStript语法
    JS拖动滑块验证
    解释型语言和编译型语言、弱类型语言和强类型语言、动态语言和静态语言的区别
    user-select 用户禁止选中
    短地址
    JS实现 Tab栏切换案例
    setAttribute()方法和 getAttribute() 方法
    JS 全局作用域和局部作用域
    数组遍历 forEach 方法
    十进制小数转换为二进制
  • 原文地址:https://www.cnblogs.com/Kissfly123/p/14488913.html
Copyright © 2011-2022 走看看