当前位置:网站首页>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
边栏推荐
- 895. longest ascending subsequence
- Electronic components distribution 1billion Club [easy to understand]
- Hisilicon 35xx realizes gt911 touch screen function "suggestions collection"
- Google Earth engine (GEE) - Global organic soil area of FAO (1992-2018)
- PostgreSQL超越MySQL
- Scratch travel photo album Electronic Society graphical programming scratch grade examination level 1 true questions and answers analysis June 2022
- 新品体验:阿里云新一代本地SSD实例i4开放公测
- Oceanwide micro fh511 single chip microcomputer IC scheme small household appliances LED lighting MCU screen printing fh511
- 投资98万美元的Saas项目失败了
- PHP crawls web pages for specific information
猜你喜欢
随机推荐
Copy 10 for one article! The top conference papers published in South Korea were exposed to be plagiarized, and the first author was "original sin"?
Tiantian mathematics serial 53: February 22
The press conference of Tencent cloud Database & CSDN engineer's ability lightweight certification is coming
StackOverflow 2022数据库年度调查
程序员坐牢了,会被安排去写代码吗?
How vscade sets auto save code
895. longest ascending subsequence
Mobile web training -flex layout test question 1
嵌入式开发:估算电池寿命的7个技巧
Stackoverflow 2022 database annual survey
华泰证券开户怎么开 怎么办理开户最安全
Mysql database literacy, do you really know what a database is
How to solve the data inconsistency between redis and MySQL?
初识exception
Fs7022 scheme series fs4059a dual two lithium battery series charging IC and protection IC
Oceanwide micro fh511 single chip microcomputer IC scheme small household appliances LED lighting MCU screen printing fh511
恒生电子:金融分布式数据库LightDB通过中国信通院多项测评
(original) [Maui] realize "floating action button" step by step
Google Earth engine (GEE) - Global organic soil area of FAO (1992-2018)
Shareit a une force exceptionnelle et se connecte au top 7 de la liste mondiale des forces IAP








