1 / 18

C++ Statements

In C++ statements are basic units of execution Each ends with ; (can use expressions to compute values) Statements introduce scopes, e.g., of (temporary) variables A (useful) statement usually has a side effect Stores a value for future use: j = i + 5;

muellers
Télécharger la présentation

C++ Statements

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. In C++ statements are basic units of execution Each ends with ; (can use expressions to compute values) Statements introduce scopes, e.g., of (temporary) variables A (useful) statement usually has a side effect Stores a value for future use: j = i + 5; Performs input or output: cout << j << endl; Directs control flow: if (j > 0) {…} else {…} Interrupts control flow: throw out_of_range; Resumes control flow: catch (RangeError &re) {…} goto considered too low-level Usually better to use break or continue If you have to use goto, you must comment why C++ Statements

  2. void Number:: operator/= (const double denom) { if (denom == 0.0) { // what to do here? } m_value /= denom; } Need to handle cases where program cannot behave normally E.g., zero denominator for division Otherwise bad things happen Program crashes Wrong results Could set value to Number::NaN I.e., a special “not-a-number” value Must avoid using a valid value… … which may be difficult (e.g., for int) Anyway, caller might fail to check for it Exceptions offer a better alternative Motivation for C++ Exception Statements

  3. void foo() { throw 2; } try { foo(); } catch (int &i) { cout << “caught ” << i << endl; } catch (...) { cout << “another exception” << endl; } Can throw any type Can catch, inspect, use, refine, rethrow exceptions By value makes local copy By reference allows modifications to be made to the original exception itself “Default” catch block is indicated by three dots Catches every type C++ Exceptions: Throw Statement Syntax

  4. C++11 standardizes a hierarchy of exception classes To access these classes #include <stdexcept> Two main kinds (subclasses) of exception Run time errors (overflow errors and underflow errors) Logic errors (invalid arguments, length error, out of range) Several other useful subclasses of exception Bad memory allocation Bad cast Bad type id Bad exception You can also declare other subclasses of these Using the class and inheritance material in later lectures C++11 Library Exception Hierarchy

  5. C++ Exceptions Interrupt Control Flow • Normal program control flow is halted • At the point where an exception is thrown • The program call stack “unwinds” • Stack frame of each function in call chain “pops” • Variables in each popped frame are destroyed • This goes on until a matching try/catch scope is reached • Control passes to first matching catch block • Can handle the exception and continue from there • Can free some resources and re-throw exception • Let’s look at the call stack and how it behaves • Good way to explain how exceptions work (in some detail) • Also a good way to understand normal function behavior

  6. In general, the call stack’s structure is fairly basic A chunk of memory representing the state of an active function call Pushed on program call stack at run-time (can observe in a debugger) g++ -s generates machine code (in assembly language) A similar feature can give exact structure for most platforms/compilers Each stack frame contains: A pointer to the previous stack frame The return address (i.e., just after point from which function was called) The parameters passed to the function (if any) Automatic (local) variables for the function Sometimes called “stack variables” Exceptions Manipulate the Function Call Stack automatic variables parameters previous frame pointer return address

  7. enum results {success, failure}; int main (int, const char *[]) { Number n(8.1); try { n /= 0.0; cout << n << endl; } catch (int) { return failure; } return success; } Stack frame for function main Pushed on program call stack With stack variable n With parameters argc and argv Note that parameters are initialized at frame creation Variables are not necessarily initialized at frame creation May occur later in called function Illustrating the Call Stack (1/8) n m_value main

  8. int main (int, const char *[]) { Number n(8.1); try { n /= 0.0; cout << n << endl; } catch (int) { return failure; } return success; } Number constructor called Stack frame created Implicit this pointer points to object in previous stack frame Illustrating the Call Stack (2/8) d Number::Number(const double d) this n m_value main

  9. Number::Number(const double d) :m_value(d) { } Enter Number constructor m_value is set in object How do we know which m_value to set? Implicit this pointer Illustrating the Call Stack (3/8) d Number::Number(const double d) this n m_value main

  10. Number::Number(const double d) :m_value(d) { } Return from constructor Its stack frame is popped Returns to main Illustrating the Call Stack (4/8) n m_value main

  11. int main (int, const char *[]) { Number n(8.1); try { n /= 0.0; cout << n << endl; } catch (int) { return failure; } return success; } Call operator/= on n New stack frame created Copy 0.0 into call as denom Setthis Illustrating the Call Stack (5/8) denom Number::operator/=(const double denom) this n m_value main

  12. Test denom against 0.0 Test succeeds throw integer 0 Illustrating the Call Stack (6/8) void Number::operator/=(const double denom) { if (denom == 0.0) { throw 0; } m_value /= denom; } denom Number::operator/=(const double denom) this n m_value main

  13. throw unwinds call stack Skips over rest of function Returns to caller Illustrating the Call Stack (7/8) void Number::operator/=(const double denom) { if (denom == 0.0) { throw 0; } value_ /= denom; } n m_value main

  14. int main (int, const char *[]) { Number n(8.1); try { n /= 0.0; cout << n << endl; } catch (int) { return failure; } return success; } We’ve reached an enclosing try/catch scope And catch expression matches So stack unwinding stops Control jumps to first matching catch block Skips over intervening coutstatement (no output!) Illustrating the Call Stack (8/8) n m_value main

  15. try { // can throw exceptions } catch (Derived &d) { // Do something } catch (Base &d) { // Do something else } catch (...) { // Catch everything else } Control jumps to first matching catch block Order matters if multiple possible matches Especially with inheritance-related exception classes Put more specific catch blocks before more general ones Put catch blocks for more derived exception classes before catch blocks for their respective base classes More Details About Catching Exceptions in C++

  16. try { // can throw exceptions } catch (Derived &d) { // Do something } catch (Base &d) { // Do something else } catch (...) { // Catch anything else, // do as much as you can throw; // rethrows it } catch(...) “Catch-all” handler, catches any type Often should at least free resources, generate an error message, etc. May rethrow exception for another handler to catch and do more throw; As of C++11 standard, rethrows a caught exception (very useful in Catch-all handlers ) More About Catching Exceptions in C++

  17. // can throw anything void Foo::baz(); // promises not to throw void Foo::baz() throw(); // promises to only throw int void Foo::baz() throw(int); // only char or int void Foo::baz() throw(char,int); Added in C++98, deprecated in C++11 Replaced with noexcept Make promises to the calling function Empty throw clause promises no exceptions Can list multiple types (comma separated) By default, a function can throw whatever it wants Throw clause limits what function body can throw But may call code that leaves off throw clause Exception Specifications (do not use them)

  18. Use exceptions to handle any cases where the program cannot behave normally Do not use exceptions as a way to control program execution under normal operating conditions Don't let a thrown exception propagate out of the main function uncaught Instead, always catch any exceptions that propagate up Then return a non-zero value to indicate program failure Don’t rely on exception specifications May be a false promise, unless you have fully checked all the code used to implement that interface No guarantees that they will work for templates, because a template parameter could leave them off and then throw Rules of Thumb for Using C++ Exceptions

More Related