c ++异常处理

In this article, we’ll take a look at performing Exception Handling in C++.

在本文中,我们将介绍在C ++中执行异常处理

Exception Handling is an important topic, especially in the context of Object-Oriented Programming. C++ is similar to Java, with the fact that it can raise and catch Exceptions.

异常处理是一个重要的主题,尤其是在面向对象编程的情况下 。 C ++与Java类似,因为它可以引发和捕获Exceptions

We denote a separate section of the code to handle exceptions, as they make things modular and easier for programmers. If any additional errors are detected, only the exception handling code must be modified.

我们在代码的单独部分中说明了处理异常的方法,因为它们使事情变得模块化,并使程序员更轻松。 如果检测到任何其他错误,则仅必须修改异常处理代码。

We must enclose any code which throws an exception under a try block. So the three major parts of Exception Handling are:

我们必须将任何引发异常的代码放在try块下。 因此,异常处理的三个主要部分是:

  • The try blocktry
  • Throwing an exception, using an optional object, along with the throw keyword.使用可选对象以及throw关键字throw异常。
  • A catch block, to handle the Exception. This block is usually immediately after the try block. The program will jump to this section immediately after a suitable exception is thrown.一个catch块,用于处理Exception。 该块通常紧接在try块之后。 引发适当的异常后,程序将立即跳至本节。

The overall structure of the program will be:

该计划的总体结构为:


try {...throw exception;
}catch(object) {...
}

Let’s investigate this in more detail, in the below sections.

让我们在以下部分中对此进行更详细的研究。



在C ++中引发异常 (Throwing an Exception in C++)

In C++ terms, we call the raising of an exception as throwing an exception.

用C ++术语来说,我们将引发异常称为抛出异常。

This is done using the throw keyword. This can take any object (or a primitive type) and pass it into the exception handling code.

这是使用throw关键字完成的。 这可以采用任何对象(或原始类型)并将其传递到异常处理代码中。

The syntax for throwing an object is:

抛出对象的语法是:


// Must enclose the code in a try block
try {int x = 0;call_function(x);if (x < 0) {// Throw the object, if something unwanted happenedthrow x;}
}

Now, the program is obviously not complete, since there is no catch block.

现在,由于没有catch块,因此程序显然未完成。

Let’s write that now!

现在就写吧!



捕捉异常 (Catching Exceptions)

We mentioned that the program will jump from the try block to a suitable catch block, if available.

我们提到,程序将从try块跳转到合适的catch块(如果有)。

A catch block is of the following structure:

catch块具有以下结构:


catch(int x) {std::cout << "Exception thrown. Object " << x << " caught.\n";
}

Whenever our function_call(x) makes x become negative, it will throw an exception, and a message will be printed.

每当我们的function_call(x)使x变为负数时,它将抛出异常,并显示一条消息。

Let’s look at the complete program now.

现在让我们看一下完整的程序。


#include <iostream>void function_call(int& x) {// Do some work, and modify the value of x, so we're passing by referenceif (x == 0) {// Set it to some negative value. We'll use this to throw an exceptionx = -10;// Throw an exception, and pass the object xthrow x;}else {x = 100;}
}int main() {int x = 0;try {function_call(x);std::cout << "If this line executes, then x != 0\n";}catch(int x) {std::cout << "Exception thrown. Object " << x << " caught.\n"; }return 0;
}

Since x was set to 0 initially, we will throw an exception, and print the modified value of x ( set to -10), showing that it has executed the catch block.

由于最初将x设置为0,我们将引发异常,并打印x的修改值(设置为-10),表明它已执行catch块。

Also, notice that the line immediately below the function_call(x) statement never gets executed, since the program directly jumps to catch.

另外,请注意,由于程序直接跳转到catch ,因此function_call(x)语句正下方的行永远不会执行。

Output

输出量


Exception thrown. Object -10 caught.

捕获所有类型的异常 (Catch-All types of Exceptions)

What if you want your code to handle all arbitrary kinds of exceptions? C++ introduces a feature which allows you to perform this, using a special matching object using ....

如果您希望代码处理所有任意种类的异常该怎么办? C ++引入了一项功能,该功能允许您使用特殊的匹配对象...来执行此操作。

To catch all kinds of exceptions, we can write catch(...) to catch every object that we throw. This is called the Default Exception and is the fallback option, when we cannot match with any of the other exceptions.

为了捕获各种异常,我们可以编写catch(...)来捕获我们抛出的每个对象。 当我们无法与其他任何异常匹配时,这称为默认异常 ,它是后备选项。

To illustrate this, here is an example.

为了说明这一点,这是一个示例。


#include <iostream>
#include <string>void function_call(int& x) {// Do some work, and modify the value of x, so we're passing by referenceif (x == 0) {// Throw an exception, and pass on the object xthrow x;}else if (x < 0) {// If x is negative, throw a random stringthrow std::string("Default String");}else {x = 100;}}int main() {for (int i=0; i>=-3; i--) {try {function_call(i);std::cout << "If this line executes, then x != 0\n";}catch(int x) {std::cout << "Exception thrown. Currently, x = " << x << " caught.\n";}catch(...) {std::cout << "Default exception. Currently, i = " << i << " caught.\n";}}return 0;
}

Output

输出量


Exception thrown. Currently, x = 0 caught.
Default exception. Currently, i = -1 caught.
Default exception. Currently, i = -2 caught.
Default exception. Currently, i = -3 caught.

As you can see, initially, when i = 0, it goes to the first catch block, since we return an integer.

如您所见,最初,当i = 0 ,它会转到第一个catch块,因为我们返回一个整数。

But, after that, since we return the string “Default String”, it does not match with the first block, and it goes to the default block.

但是,此后,由于我们返回字符串“ Default String”,因此它与第一个块不匹配,并且转到了默认块。

Unfortunately, C++ does not give us a way to pass the object in the default case, so we cannot get the “Default String” string. This shows that we must use this only for adding functionality to our code, to account for unknown errors.

不幸的是,C ++没有提供在默认情况下传递对象的方法,因此我们无法获取“ Default String”字符串。 这表明我们只能将其用于为代码添加功能,以解决未知错误。

传递指向异常的指针和引用 (Passing Pointers and References to Exceptions)

This is also possible since we’re working with C++!

由于我们正在使用C ++,因此这也是可能的!

A general rule is to handle all the freeing related to the pointers in the exception handling code.

一般规则是处理异常处理代码中与指针相关的所有释放。


try {call_function(base_ptr);
}
// Catch the Custom Exception Pointer using our Exception Class
catch(MyException* ex_obj) {delete ex_obj;
}// Catch the reference to an Exception Class object
catch(MyException& ex_obj) {// Do stuff ...
}

Let’s consider the below exception handler class MyException.

让我们考虑下面的异常处理程序类MyException


#include <iostream>
#include <string>class MyException {public:int err; // Error Codestd::string err_msg; // String containing Error MessageMyException(int val = 0) {// Base Constructorerr = val;switch(val) {case(-1): err_msg = "Case -1"; break;case(-2): err_msg = "Case -2"; break;case(-3): err_msg = "Case -3"; break;default: err_msg = "\0"; // No error message for other cases}}~MyException() {std::cout << "Destructor for Exception Class called\n";}
};void function_call(int& x) {// Do some work, and modify the value of x, so we're passing by referenceif (x <= 0) {// Throw an exception, and pass on the object xMyException* ex = new MyException(x);throw ex; // Throw the exception pointer}else {x = 100;}}int main() {for (int i=0; i>=-3; i--) {try {function_call(i);std::cout << "If this line executes, then x != 0\n";}catch(MyException* ex) {std::cout << "Exception thrown. Error Message: " << ex->err_msg << "\n";// Remember to free the pointer to the Exception!!!delete ex;}catch(...) {std::cout << "Default exception. Currently, i = " << i << " caught.\n";}}return 0;
}

Instead of passing on the integer directly, we construct an exception class and pass a pointer to an object, which has the relevant error code and error message.

与其直接传递整数,不如构造一个异常类,然后将一个指针传递给一个对象,该对象具有相关的错误代码和错误消息。

Here, you can see how powerful using an Exception Class handler for this is!

在这里,您可以看到使用Exception Class处理程序的强大功能!

Not only can we add debug messages to it, in the constructor, but when we actually pass it around, we only move the pointer, which is 8 bytes only! This is something other languages like Java can’t do easily.

我们不仅可以在构造函数中向其添加调试消息,而且在实际传递该消息时,我们仅移动了仅8个字节的指针! 这是其他语言(例如Java)无法轻松完成的。

Output

输出量


Exception thrown. Error Message:
Destructor for Exception Class called
Exception thrown. Error Message: Case -1
Destructor for Exception Class called
Exception thrown. Error Message: Case -2
Destructor for Exception Class called
Exception thrown. Error Message: Case -3
Destructor for Exception Class called

Indeed, this is what we expect! Only for values of -1, -2, and -3, we’ve instructed the constructor to set error messages. For other values, it is simply a NULL string.

确实,这就是我们的期望! 仅针对值-1,-2和-3,我们指示构造函数设置错误消息。 对于其他值,它只是一个NULL字符串。



C ++中异常处理的其他要点 (Additional Takeaways for Exception Handling in C++)

  • When using try and catch blocks, there is NO implicit type conversion taking place. So a char is not converted to an int, when passed to exception handlers.当使用trycatch块, 存在隐式类型转换的发生。 因此,当将char传递给异常处理程序时,不会将其转换为int
  • Always use a catch block if you use a try block. Otherwise, if you throw an exception, this will result in an abnormal termination of the program.如果使用try块,请始终使用catch块。 否则,如果引发异常,则将导致程序异常终止。
  • Modularize your code so that your core program logic is different from the Error handling logic. For Exceptions, try to use related Exception Handler classes and polymorphism to handle errors.模块化您的代码,以便您的核心程序逻辑与错误处理逻辑不同。 对于异常,请尝试使用相关的异常处理程序类和多态性来处理错误。
  • If you use raw pointers, always remember to free them in your catch blocks! If you find raw points too troublesome, use smart pointers instead!如果您使用原始指针,请始终记住在catch块中释放它们! 如果发现原始点太麻烦,请改用智能指针 !

I hope you found this article useful for learning more about Exception Handling in C++. If you have any doubts, or even found any mistakes, please do mention them in the comment section below!

我希望您发现本文对了解C ++中的异常处理有用。 如果您有任何疑问,甚至发现任何错误,请在下面的评论部分中提及它们!



参考资料 (References)

  • StackOverflow Question on Exception Handling in C++有关C ++中异常处理的StackOverflow问题


翻译自: https://www.journaldev.com/37644/exception-handling-in-c

c ++异常处理

c ++异常处理_C ++中的异常处理相关推荐

  1. Arm64中的异常处理

    闲话 最近优化环境中出现了多次不同种类的异常,其他文章中也有提及,为此专门去研究了一下Arm64的异常处理机制和代码,之前主要的开发和应用环境为X86,ARM接触很少,也没有机会去研究和学习,总以为不 ...

  2. c#异常处理_C#中的异常处理

    c#异常处理 What an exception is? 有什么例外? An exception is a runtime error; that means an abnormal situatio ...

  3. kotlin中的异常处理_如何使用assertFailsWith在Kotlin中测试异常

    kotlin中的异常处理 by Daniel Newton 丹尼尔·牛顿 如何使用assertFailsWith在Kotlin中测试异常 (How to test exceptions in Kotl ...

  4. 编写高质量代码改善C#程序的157个建议——建议86:Parallel中的异常处理

    建议86:Parallel中的异常处理 建议85阐述了如何处理Task中的异常.由于Task的Start方法是异步启动的,所以我们需要额外的技术来完成异常处理.Parallel相对来说就要简单很多,因 ...

  5. SpringMVC 中的异常处理

    SpringMVC 中的异常处理 异常处理的思路 系统中异常包括两类:预期异常和运行时异常 RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发.测试通过手段减 ...

  6. PHP如何进行错误与异常处理(PHP7中的异常处理和之前版本异常处理的区别)

    PHP如何进行错误与异常处理(PHP7中的异常处理和之前版本异常处理的区别) 一.总结 一句话总结: throwable接口+Error类 在PHP7更新中有一条:更多的Error变为可捕获的Exce ...

  7. 【转】Java中关于异常处理的十个最佳实践

    原文地址:http://www.searchsoa.com.cn/showcontent_71960.htm 导读:异常处理是书写强健Java应用的一个重要部分,Java许你创建新的异常,并通过使用 ...

  8. Swift41/90Days - 面向轨道编程 - Swift 中的异常处理

    问题 在开发过程中,异常处理算是比较常见的问题了. 举一个比较常见的例子:用户修改注册的邮箱,大概分为以下几个步骤: 接收到一个用户的请求:我要修改邮箱地址 验证一下请求是否合法,将请求进行格式转化 ...

  9. Laravel 中的异常处理

    Laravel 中的异常处理 参考文章: (1)Laravel 中的异常处理 (2)https://www.cnblogs.com/feiffy/p/10253842.html (3)https:// ...

最新文章

  1. OceanBase如何解决支付宝数据库的高一致性
  2. 在linux c 以结构体形式写文件 结构体参数如何在函数中传递,Linux安全审计机制模块实现分析(16)-核心文件之三auditsc.c文件描述及具体变量、函数定义...
  3. redis java 性能_Redis 性能优化
  4. [Go] golang设置运行的cpu数
  5. 文本框灰色文字提示,鼠标点击文字消失
  6. Java用SAX解析XML
  7. linux sh 编程,Linux shell 编程入门
  8. 在Serverless Kubernetes集群中轻松运行Argo Workflow
  9. iphone 2x 3x_iPhone X的未来:从现实到荒诞
  10. Android 常用数据操作封装类案例
  11. 对JQuery中Ajax应用与jQuery插件的理解与笔记
  12. 为你解惑之WPF经典9问详解
  13. kafka-eagle 使用配置及远程jmx端口设置遇到的问题
  14. Python程序员的就业方向及就业薪资,你都了解吗?
  15. Java 快乐练习口算
  16. Error: unknown command “push“ for “helm“ Helm安装push插件
  17. 分销小程序定制开发|分销系统开发对商家有哪些好处?
  18. Django框架特点
  19. 玩电脑玩出的 Linux 专家 - Google(谷歌)开发者日演讲者之苏哲
  20. Apache Shiro RememberMe 1.2.4 反序列化过程命令执行漏洞【原理扫描】

热门文章

  1. java事务的类型——面试被问到
  2. cxGrid 怎样才能让不自动换行 WordWrap:=false
  3. [杂谈] 2013年新目标
  4. excel批量导入数据
  5. ArcGIS API for Silverlight/WPF/Windows Phone/Android 插件下载地址
  6. 搜狗云输入法对外提供调用体验
  7. Xorg可以使用hot-plug了,不过配置很麻烦
  8. 9月我的第一次,新的感悟
  9. 初次使用uwsgi:no python application found, check your startup logs for errors
  10. 55)PHP,在html嵌套PHP写法