C++中的异常

一,异常的推演

1.函数与异常

  平时我们在函数中出现异常情况时通常通过return终止函数并返回一个值,然后在函数上层来获取值并判断是什么异常情况。因为函数是栈结构的,所以return的时候是通过栈结构逐步往上的,不能够跨函数直接抛出,不方便。所以C++推出了异常机制,通过异常机制我们可以轻松的捕获要出现的异常。

2.C++中异常的基本演示

# include<iostream>
using namespace std;

/* 定义求商函数,如果除数为0,抛出double类型异常 */
double div(double d1, double d2)
{
    if (d2 == 0)
    {
        throw d2;
    }
    return d1 / d2;
}

int main()
{
    /* try...catch语句来捕获异常 */
    try
    {
        double result = div(1.02, 0.0);
    }
    catch (double e)
    {
        /* C++中的异常严格要求类型匹配,即抛出什么的异常就catch什么类型的异常 */
        cout << e << "不能作除数" << endl;
    }
    catch (...)
    {
        cout << "未知异常" << endl;
    }

    return 0;
}

 3.C++中异常的总结

  • 异常的捕捉严格匹配数据类型,不支持类型自动转换,throw的是int类型则catch的必须是int类型否则不会匹配。
  • 一般我们在异常最后加入catch(...)这样能够捕获任意异常。

二,自定义异常类

1.异常类

  按照面向对象的思维,我们的异常也应该是一个对象,所以在抛出异常的时候,我们通常自定义一个异常类,然后把异常信息放入异常类中,然后在捕捉到异常对象的时候,再调用对象的方法,打印出异常的信息。

2.异常类代码演示

# define _CRT_SECURE_NO_WARNINGS
# include<iostream>
using namespace std;

/* 自定义异常类 */
class MyException
{
private:
    char * content;
public:
    /* 异常类构造函数 */
    MyException(const char * content)
    {
        this->content = new char[strlen(content) + 1];
        strcpy(this->content, content);
        cout << "异常类有参构造函数执行" << endl;
    }
    /* 异常类拷贝构造函数 */
    MyException(const MyException& me)
    {
        this->content = new char[strlen(me.content) + 1];
        strcpy(this->content, me.content);
        cout << "异常类拷贝构造函数执行" << endl;
    }
    /* 异常类析构函数 */
    ~MyException()
    {
        if (this->content != NULL)
        {
            delete[] this->content;
            this->content = NULL;
        }
        cout << "异常类的析构函数执行" << endl;
    }
    /* 异常类抛出异常信息 */
    void toString()
    {
        cout << this->content << endl;
    }
};

/* 定义测试异常的函数 */
double divide(double d1, double d2)
{
    if (d2 == 0)
    {
        throw MyException("除数不能为0");
        //throw new MyException("除数不能为0");
    }
    return d1 / d2;
}

int main()
{
    try
    {
        double result = divide(1, 0);
        cout << "result = " << result << endl;
    }
    catch (MyException e)
    {
        // catch的异常是元素类型,执行的是拷贝构造函数,存在两个异常对象,释放两个异常对象,不合理
        e.toString();
    }
    catch (MyException * e)
    {
        // catch的异常是指针类型,必须我们手动调用delete方法才能调用析构函数,不合理
        e->toString();
        delete e;
    }
    catch (MyException& e)
    {
        // catch的是引用类型,是原先抛出的对象,会自动执行析构函数,我们使用引用来接收抛出的异常对象
        e.toString();
    }
    catch (...)
    {
        cout << "未知异常" << endl;
    }

    return 0;
}

3.自定义异常类总结

  • 抛出异常对象通常用引用的方式来catch这个对象,如果是元素catch异常对象则会执行拷贝构造函数,创建两个重复异常对象并释放两次对象,所以说不合理。如果catch的是指针类型,不会自动调用该对象的析构函数必须我们手动delete,也不符合自动调用的逻辑,所以使用引用的方式来catch异常对象。

三,标准异常类

1.标准异常类

  C++中提供了标准的异常类,需要# include<exception>,标准异常类为exception,该类有个what函数,可以打印异常对象的异常信息。该what函数是虚函数,我们需要继承exception类并重写该what函数,在捕捉异常的时候,我们用父类的引用来接收自定义的标准异常类的子类对象(类型兼容性原则),然后打印该异常信息即可。

2.标准异常类演示

# include<iostream>
# include<exception>
using namespace std;

/* 继承自标准异常类 */
class DivException :public exception
{
private:
    const char * ptr;
public:
    /* 构造函数接收异常信息 */
    DivException(const char * ptr)
    {
        this->ptr = ptr;
    }
    /* 重写what函数 */
    virtual char const * what() const
    {
        cout << this->ptr << endl;
        return ptr;
    }
};
/* 测试异常函数 */
int divi(int a, int b)
{
    if (b == 0)
    {
        throw DivException("除数不能为0");
    }
    return a / b;
}

int main()
{
    try
    {
        divi(10, 0);
    }
    catch (exception& e)
    {
        /* 使用exception引用接收自定义的子类对象 */
        e.what();
    }
    catch (...)
    {
        cout << "未知异常" << endl;
    }

    return 0;
}
时间: 2024-10-09 03:28:16

C++中的异常的相关文章

Laravel 5.4 中的异常处理器和HTTP异常处理实例教程

错误和异常是处理程序开发中不可回避的议题,在本地开发中我们往往希望能捕获程序抛出的异常并将其显示打印出来,以便直观的知道程序在哪里出了问题并予以解决,而在线上环境我们不希望将程序错误或异常显示在浏览器中(出于安全考虑),这个时候我们仍然要捕获异常,只不过不是显示到浏览器中,而是记录到日志中,方便日后排查问题. 百牛信息技术bainiu.ltd整理发布于博客园 Laravel当然支持PHP原生的错误和异常处理,但是在此基础上进行了一些封装处理,从而更方便在不同开发环境切换以及对错误和异常的处理.

[C++11 并发编程] 16 在期望中保存异常

如果在异步线程中发生了异常,等待期望的线程如何才能知道并且正确的处理异常呢? 假设有如下所示的一个求平方根的函数: double square_root(double x) { if(x<0) { throw std::out_of_range("x<0"); } return sqrt(x); } 通常,如果在当前线程上下文中调用square_root(),方法如下: double y=square_root(-1); 在异步线程中调用square_root(),方法如下

Java中的异常和处理详解

原文出处:代码钢琴家 简介 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常.异常发生时,是任程序自生自灭,立刻退出终止,还是输出错误给用户?或者用C语言风格:用函数返回值作为执行状态?. Java提供了更加优秀的解决办法:异常处理机制. 异常处理机制能让程序在异常发生时,按照代码的预先设定的异常处理逻辑,针对性地处理异常,让程序尽最大可能恢复正常并继续执行,且保持代码的清晰. Java中的异常可以是函数中的语句执行时引发的,也可以是程序员通过throw 语句手

编写高质量代码改善C#程序的157个建议——建议66:正确捕获多线程中的异常

建议66:正确捕获多线程中的异常 多线程的异常处理需要采用特殊的方式.一下这种方式会存在问题: try { Thread t = new Thread((ThreadStart)delegate { throw new Exception("多线程异常"); }); t.Start(); } catch (Exception error) { MessageBox.Show(error.Message + Environment.NewLine + error.StackTrace);

WCF中的异常

   一.考虑到安全因素,为了避免将服务端的异常发送给客户端.默认情况下,服务端出现异常会对异常屏蔽处理后,再发送到客户端.所以客户端捕捉到的异常都是同一个FaultException异常. 例如在服务端直接产生一个空引用异常,客户端捕获到的是上述异常. 服务端: class Program { static void Main(string[] args) { ServiceHost host = new ServiceHost(typeof(SayHello)); host.AddServi

JAVA中的异常(异常处理流程、异常处理的缺陷)

异常处理流程 1)首先由try{...}catch(Exception e){ System.out.println(e); e.printStackTrace(); }finally{...}结构 2)当JVM遇到异常时,会产生一个Exception对象 或 继承自Exception的子类的对象. 3)将异常对象向上层(调用它的代码块)抛出,知道碰到一个catch块(作相应处理) 或 一直抛到了最外层(导致程序异常终止).(并停止异常之后的代码的执行,但是finally块中的代码还会执行!换句

java中关于异常的处理

初学java的时候,当我们碰到异常时,一般会把异常直接throws抛出去,或则在catch的时候,简单的写一句打印异常信息,但是在实际开发中,是不能这么做的.如果我们将底层的某一个异常简单的print出去,那么这个异常的捕获是没有起到任何作用,反而给编译器一个"异常已处理"的假象,导致有异常的程序会继续往下执行,这是不允许的:如果我们直接将异常抛出去,抛给上一层,也是徒劳的,反而给上一层带来麻烦. 为了避免这样的情况发生,我们一般会将异常进行转换,将编译时异常转变成运行时异常,再thr

【PLSQL】Oracle中的异常

一.摘要 在PLSQL程序开发过程中,很重要的部分就是对程序异常的监控和处理,包括如何触发异常,何时进行处理,如何进行处理,是否将程式中的所有异常集中在一起,通过公共异常处理的procedure或function,如果没有完善的程式处理机制,很难说该程式是一只健壮的程式,当程式遇到很多类型或者量很多资料时,系统若没有异常处理必然会导致程式的出错 当预判到了某些异常,需要对预判到的异常进行合适相应的处理,是否抛出异常还是忽略还是其他 当然程式没有预判到或者是一些未知的异常遇到,所以异常处理模块也要

C++中的“error:LNK2005 已经在*.obj中定义”异常问题

C++中的“error:LNK2005 已经在*.obj中定义”异常问题 异常现象如下:

.NET中的异常和异常处理

.NET中的异常(Exception) .net中的中异常的父类是Exception,大多数异常一般继承自Exception. 可以通过编写一个继承自Exception的类的方式,自定义异常类! 异常处理机制 Try { 可能发生异常的代码 后续代码 } Try以外的代码 catch(Exception e) { } finally { } 上述代码描述如下 1.谁能执行 在异常处理中,一旦try里面有了问题,程序会放弃异常的后续代码直接跳到catch中. 执行完了catch中的代码,继续执行T