Exceptions, the program detects the current situation and will run exceptionally when it exceeds its processing power.
For example, common exceptions have zero dividing problems, database connection loss input needs a number of cases given alphabetic input
Typical exception handling consists of the following sections: try blocks, statements that might be abnormal are placed in try blocks, an exception type is the parameter in the catch bracket, and different types are used to determine different exceptions
try{ program-statements }catch(exception-declaration){ handler-statments }catch(exception-declaration){ handler-statments }
Exceptions are not only triggered by the system itself, but also by human beings.
throw runtime_error("this is a throw error")
One of the basic goals of exception handling is to minimize abnormal exit of programs and to fix running exceptions as much as possible
The try statement block also provides such a possibility for us.
Looking at this code, we receive sales information for two books from the user input, and then determine whether the same is added to the same, otherwise the data is discarded.
But the code exits without completing the task under different circumstances, giving the user only an insignificant hint.
Sales_item item1, item2; cin >> item1 >> item2; if(item1.isbn() == item2.isbn()) { cout << item1 + item2 << endl; return 0 } else { cerr << "Data must refer to same ISBN" << endl; return -1; }
The following code throws an exception in case of an input error. The advantage of throwing an exception is that it must be handled at the call, otherwise the program will exit abnormally.
It’s obviously not possible to throw an exception just because we need to catch it to get there
// Change the above code to a version that throws an exception. Sales_item item1, item2; cin >> item1 >> item2; if(item1.isbn() != item2.isbn()) { throw runtime_error("Data must refer to same ISBN"); } cout << item1 + item2 << endl;
According to the request of capture exception, we upgraded the code to the following styles
// But the above parts will terminate if the different ISBN programs are entered.// At this point we need try blocks for capturing. Sales_item item1, item2; while(cin >> item1 >> item2) { try { if(item1.isbn() != item2.isbn()) { throw runtime_error("Data must refer to same ISBN"); } cout << item1 + item2 << endl; // Matching time operation and output break; } catch(runtime_error err) { // Remind users that two ISBN must be consistent, asking whether to re-enter. cout << err.what() << "\nTyr Again? Enter y or n." << endl; char c; cin >> c; if(!cin || c == 'n') break; } }
Such an exception can be captured, and it will not pose a fatal threat to the operation of the program.
The search sequence after exception throwing is the invocation of the entry function, which is related to the reverse search of the current running code layer by layer.
Until the catch block for exception handling is found, or the entry main function is not found, the program gives it to a standard function with the name terminate.
The behavior of this function is related to the system, but the general principle is to terminate the current program and abort it.
Abnormal type in standard library
A total of 4 header files define the exception type.
exceptionHeader files, stdexcept header files, new header files (bad_alloc), type_info header files (bad_cast)
The runtime_error used in this section belongs to stdexcept.
The following code is posted for everyone to compile and debug.
39.cpp
//39.cpp #include <iostream> #include "Sales_item.h" using std::cin; using std::cout; using std::endl; using std::runtime_error; int main() { Sales_item item1, item2; while(cin >> item1 >> item2) { try { if(item1.ISBN() != item2.ISBN()) { throw runtime_error("Data must refer to same ISBN"); } cout << item1 + item2 << endl; break; } catch(runtime_error err) { // Remind users that two ISBN must be consistent, asking whether to re-enter. cout << err.what() << "\nTyr Again? Enter y or n." << endl; char c; cin >> c; if(!cin || c == 'n') break; } } }
Sales_item.h
// Sales_item.h #ifndef SALESITEM_H #define SALESITEM_H #include <iostream> #include <string> class Sales_item{ public: Sales_item(const std::string &book):isbn(book),units_sold(0),revenue(0.0){} Sales_item(std::istream &is){ is >> *this;} friend std::istream& operator>>(std::istream &,Sales_item &); friend std::ostream& operator<<(std::ostream &,const Sales_item &); public: Sales_item & operator+=(const Sales_item&); public: double avg_price() const; bool same_isbn(const Sales_item &rhs)const{ return isbn == rhs.isbn; } std::string ISBN(){return isbn;} Sales_item():units_sold(0),revenue(0.0){} public: std::string isbn; unsigned units_sold; double revenue; }; using std::istream; using std::ostream; Sales_item operator+(const Sales_item &,const Sales_item &); inline bool operator==(const Sales_item &lhs,const Sales_item &rhs){ return lhs.units_sold == rhs.units_sold && lhs.revenue == rhs.revenue && lhs.same_isbn(rhs); } inline bool operator!=(const Sales_item &lhs,const Sales_item &rhs){ return !(lhs == rhs); } inline Sales_item & Sales_item::operator +=(const Sales_item &rhs){ units_sold += rhs.units_sold; revenue += rhs.revenue; return *this; } inline Sales_item operator+(const Sales_item &lhs,const Sales_item &rhs){ Sales_item ret(lhs); ret += rhs; return ret; } inline istream& operator>>(istream &in,Sales_item &s){ double price; in >> s.isbn >> s.units_sold >> price; if(in) s.revenue = s.units_sold * price; else s = Sales_item(); return in; } inline ostream& operator<<(ostream &out,const Sales_item &s){ out << s.isbn << "\t" <<s.units_sold << "\t" << s.revenue << "\t" << s.avg_price(); return out; } inline double Sales_item::avg_price() const{ if(units_sold) return revenue/units_sold; else return 0; } #endif // SALESITEM_H