当前位置:网站首页>First knowledge of exception
First knowledge of exception
2022-06-28 13:25:00 【GarryLau】
Types of exceptions that can be thrown ( in fact , You can throw any type ):
1. Basic and compound types ;
2. Class types
Use ( class ) The benefits of throwing objects as exceptions :
1. The class name of the object can convey information ;
2. Objects can store information , Include the string used to describe the exception .
( remarks : It is suggested that const Reference catch exception )
If there are uncaught exceptions , Will call the built-in terminate() function , In this function call abort() To terminate the program
Functions that do not throw lists can throw any exceptions . have noexcept Or empty throw list throw() The function of cannot throw any exceptions .
throw yes C++ Key words of , This is the only way to throw an exception .
To throw an exception , Or take the initiative to use throw, Or it calls other contains throw Methods .
#pragma once
#include <iostream>
#include <stdexcept>
namespace test_exception {
auto testThrow() -> void {
int a = 10, b = 0;
try {
if(0 == b) {
throw std::runtime_error("divided 0");
}
else{
int c = a / b;
}
}
catch(std::runtime_error& e){
std::cerr << "exception occurs: " << e.what() << std::endl;
}
}
auto testWantThrow() -> void {
int a = 10, b = 0;
try {
int c = a / b; // try There is no... In the statement block throw, So no exception will be thrown
}
catch(...){
std::cerr << "exception occurs." << std::endl;
}
}
auto main() -> int {
std::cout << "testing exception_errorprocess..." << std::endl;
testThrow();
testWantThrow();
std::cout << "------------------------------" << std::endl;
return 0;
}
}
Output :
1. Exception example
#pragma once
#include <stdexcept>
#include <exception>
#include <iostream>
namespace test_exception {
float divide1(float a, float b) {
if(b == 0){
//throw "divided by zero.";
//throw std::invalid_argument("Divide by zero");
//throw std::exception();
throw 5;
}
return a / b;
}
float divide2(float a, float b) noexcept/*throw()*/{
if(b == 0){
//throw "divided by zero.";
throw std::invalid_argument("std::invalid_argument, Divide by zero!");
//throw std::exception();
//throw 5;
}
return a / b;
}
#if 1
float divide3(float a, float b) throw(int, std::invalid_argument){
// Indicates that only... Can be thrown int, std::invalid_argument Two types of exceptions
if(b == 0){
//throw "divided by zero."; // This type cannot throw
throw std::invalid_argument("std::invalid_argument, Divide by zero!"); // This type can be thrown
//throw std::exception(); // This type cannot throw
//throw 5; // This type can be thrown
}
return a / b;
}
#endif
auto catchSample1() -> void {
int a = 10;
int b = 0;
try {
std::cout << divide1(a, b) << std::endl;
}
catch(const char* e){
std::cout << e << std::endl;
}
catch(const std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
catch(const std::exception& e){
// increase const Attributes do not affect the purpose of the match , That is, this sentence is related to std::exception& e Can match std::exception Exception of type
std::cout << "+++" << e.what() << "+++" << std::endl;
}
catch(int e){
std::cout << "catching integer\n";
}
catch(...){
// Wildcards that match all exception types at three points , You can use this technique to ensure that all possible exceptions are caught
std::cout << "unknow exception" << std::endl;
}
}
auto catchSample2() -> void {
int a = 10;
int b = 0;
std::cout << "entering catchSample2()...............\n";
try {
std::cout << divide2(a, b) << std::endl;
}
catch(const std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
catch(...){
std::cout << "unknow exception" << std::endl;
}
std::cout << "exiting catchSample2()...............\n";
}
auto main() -> void {
std::cout << "testing exception......" << std::endl;
catchSample1();
catchSample2();
std::cout << "--------------------------------------\n";
}
}
float divide2(float a, float b) noexcept It is defined to prohibit throwing exceptions , So when you divide by 0( Exception occurs ) At the time catchSample2() No capture , It's left to the operating system ( It's usually called terminate()).
The above program output :
__cplusplus: 201103
testing exception......
catching integer
entering catchSample2()...............
terminate called after throwing an instance of 'std::invalid_argument'
what(): std::invalid_argument, Divide by zero!
It should be noted that for the code like the above float divide3(float a, float b) throw(int, std::invalid_argument) Throw list C++17 No longer support , So if you use C++17 The standard compiler will report the following error :error: ISO C++17 does not allow dynamic exception specifications
# specify the C++ standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
2. Exception hierarchy

You need to be careful when catching exceptions in the class hierarchy :
1. When using polymorphism to catch exceptions , Be sure to capture by reference . Truncation can occur if exceptions are caught by value , The information of the object is lost .
2.catch Statements should appear in the order in which the restrictions are reduced ( Put the special in front 、 Usually placed in the back ). For example, if you want to capture invalid_argument abnormal , Then you should invalid_argument Put it in exception front ; If invalid_argument Put it in exception Back then invalid_argument Can never execute . See the following two examples for details :
#pragma once
#include <stdexcept>
#include <exception>
#include <iostream>
namespace test_exception {
float divide(float a, float b) {
if(b == 0){
throw std::invalid_argument("Divide by zero");
//throw std::exception();
}
return a / b;
}
auto catchSample() -> void {
int a = 10;
int b = 0;
try {
std::cout << divide(a, b) << std::endl;
}
catch(const std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
catch(const std::exception& e){
std::cout << "+++" << e.what() << "+++" << std::endl;
}
catch(...){
std::cout << "unknow exception" << std::endl;
}
}
auto main() -> void {
std::cout << "testing exception......" << std::endl;
catchSample();
std::cout << "--------------------------------------\n";
}
}
The results are as follows :
__cplusplus: 201703
testing exception......
Divide by zero
--------------------------------------
The end.
#pragma once
#include <stdexcept>
#include <exception>
#include <iostream>
namespace test_exception {
float divide(float a, float b) {
if(b == 0){
throw std::invalid_argument("Divide by zero");
//throw std::exception();
}
return a / b;
}
auto catchSample() -> void {
int a = 10;
int b = 0;
try {
std::cout << divide(a, b) << std::endl;
}
catch(const std::exception& e){
std::cout << "+++" << e.what() << "+++" << std::endl;
}
catch(const std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
catch(...){
std::cout << "unknow exception" << std::endl;
}
}
auto main() -> void {
std::cout << "testing exception......" << std::endl;
catchSample();
std::cout << "--------------------------------------\n";
}
}
The results are as follows :
__cplusplus: 201703
testing exception......
+++Divide by zero+++
--------------------------------------
The end.
3. Custom exception classes
It is suggested to start from the standard exception Implement custom exception classes directly or indirectly .
When a piece of code throws an exception , The thrown value or object is copied ,
That is, construct a new object from the old object by using the copy constructor ; Replication is a must ,
Because the original object is higher in the stack , Therefore, it is possible to go out of scope before the exception is caught ( So it will be destroyed , The memory it occupies will be reclaimed ). therefore , If the object of the written class is thrown as an exception , Objects must be able to be copied , This means that if memory is dynamically allocated , Destructor must be written 、 Copy constructors and assignment operators .P296
Tips : Objects thrown as exceptions are copied at least once by value , Catching exceptions by reference avoids unnecessary duplication
#pragma once
#include <stdexcept>
#include <string>
#include <iostream>
#include <fstream>
namespace test_exception {
class FileError : public std::runtime_error {
public:
FileError(const std::string& filename): filename_(filename), msg_(""), std::runtime_error(""){
}
virtual const char* what() const noexcept override{
return msg_.c_str();}
protected:
std::string filename_, msg_;
};
class FileOpenError : public FileError {
public:
FileOpenError(const std::string& filename): FileError(filename){
msg_ = std::string("Unable to open ") + filename_;
}
};
class FileReadError : public FileError {
public:
FileReadError(const std::string& filename, int linenumber): FileError(filename), linenum_(linenumber){
msg_ = std::string("Exception occurs in file ") + filename_ + std::string(", line ") + std::to_string(linenum_);
}
protected:
int linenum_;
};
auto main() -> void {
std::cout << "testing exception......" << std::endl;
std::string filename("../doc/daisy.txt");
std::ifstream in_file(filename);
try {
if(in_file.fail()){
throw FileOpenError(filename);
}
std::string line;
int linenum = 0;
while(std::getline(in_file, line)){
linenum++;
std::cout << line << std::endl;
}
if(!in_file.eof()){
in_file.close();
throw FileReadError(filename, linenum);
}
}
catch(const FileOpenError& e){
std::cout << "Line: " << __LINE__ << ", " << e.what() << std::endl;
}
catch (const FileReadError& e){
std::cout << "Line: " << __LINE__ << ", " << e.what() << std::endl;
}
catch(...){
std::cout << "unknow error occurs." << std::endl;
}
in_file.close();
std::cout << "--------------------------------------\n";
}
}
daisy.txt The content in :
D:/daisy/5547758_eea9edfd54_n.jpg
D:/daisy/5673551_01d1ea993e_n.jpg
D:/daisy/5673728_71b8cb57eb.jpg
D:/daisy/5794835_d15905c7c8_n.jpg
D:/daisy/5794839_200acd910c_n.jpg
The above code output :
__cplusplus: 201703
testing exception......
D:/daisy/5547758_eea9edfd54_n.jpg
D:/daisy/5673551_01d1ea993e_n.jpg
D:/daisy/5673728_71b8cb57eb.jpg
D:/daisy/5794835_d15905c7c8_n.jpg
D:/daisy/5794839_200acd910c_n.jpg
--------------------------------------
The end.
Reference
1.Marc Gregoire, Nicholas A. Solter, Scott J. Kleper. C++ Advanced programming ( The first 2 edition ). tsinghua university press ,2012
边栏推荐
- Mature case and source code of hash quiz game system development technology
- Tencent tangdaosheng: facing the new world of digital and real integration, developers are the most important "architects"
- 一文抄 10 篇!韩国发表的顶级会议论文被曝抄袭,第一作者是“原罪”?
- 弹性盒子自动换行小Demo
- 恒生电子:金融分布式数据库LightDB通过中国信通院多项测评
- Resume template Baidu online disk
- 1015.摘花生
- (原创)【MAUI】一步一步实现“悬浮操作按钮”(FAB,Floating Action Button)
- Jerry's wif interferes with Bluetooth [chapter]
- 初识exception
猜你喜欢

Centos6.5 php+mysql MySQL library not found

FS7022方案系列FS4059A双节两节锂电池串联充电IC和保护IC

Embedded development: seven techniques for estimating battery life
![[today in history] June 28: musk was born; Microsoft launches office 365; The inventor of Chua's circuit was born](/img/bf/09ccf36caec099098a22f0e8b670bd.png)
[today in history] June 28: musk was born; Microsoft launches office 365; The inventor of Chua's circuit was born

为什么越来越多的用户放弃 Swagger,选择Apifox

Solution to directory access of thinkphp6 multi-level controller

How does Quanzhi v853 chip switch sensors on Tina v85x platform?

Vscode如何设置代码保存后自动格式化

Align content attribute in flex layout

Stm32f1 and stm32cubeide programming example - matrix keyboard driver
随机推荐
嵌入式设计与开发项目-液位检测告警系统
词云的可视化设计教程
Vscode shortcut key
中国数据库技术大会(DTCC)特邀科蓝SUNDB数据库专家精彩分享
FS7022方案系列FS4059A双节两节锂电池串联充电IC和保护IC
移动Web实训DAY-2
真香啊!最全的 Pycharm 常用快捷键大全!
FH511+TP4333组成一个户外移动电源照明野营灯方案。
哈希竞猜游戏系统开发技术成熟案例及源码
c语言中的类结构体-点号
List集合转数组
简历模板百度网盘自取
其他国产手机未能填补华为的空缺,苹果在高端手机市场已无对手
Mobile web training day-2
Centos7 - installing mysql5.7
Class structure in C language - dot
Vscode如何设置代码保存后自动格式化
股票网上开户及开户流程怎样?手机开户是安全么?
我呕血收集融合了来自各路经典shell书籍的脚本教学,作为小白的你快点来吧
从pdb源码到frame帧对象