14.x — Chapter 14 comprehensive quiz

Chapter review

Exception handling provides a mechanism to decouple handling of errors or other exceptional circumstances from the typical control flow of your code. This allows more freedom to handle errors when and how ever is most useful for a given situation, alleviating many (if not all) of the messiness that return codes cause.

A throw statement is used to raise an exception. Try blocks look for exceptions thrown by the code written or called within them. These exceptions get routed to catch blocks, which catch exceptions of particular types (if they match) and handle them. By default, an exception that is caught is considered handled.

Exceptions are handled immediately. If an exception is raised, control jumps to the nearest enclosing try block, looking for catch handlers that can handle the exception. If no try block is found or not catch blocks matches, the stack will be unwound until a handler is found. If no handler is found before the entire stack is unwound, the program will terminate with an unhandled exception error.

Exceptions of any data type can be thrown, including classes.

Catch blocks can be configured to catch exceptions of a particular data type, or a catch-all handler can be set up by using the ellipses (…). A catch block catching a base class reference will also catch exceptions of a derived class. All of the exceptions thrown by the standard library are derived from the std::exception class (which lives in the exception header), so catching a std::exception by reference will catch all standard library exceptions. The what() member function can be used to determine what kind of std::exception was thrown.

Inside a catch block, a new exception may be thrown. Because this new exception is thrown outside of the try block associated with that catch block, it won’t be caught by the catch block it’s thrown within. Exceptions may be rethrown from a catch block by using the keyword throw by itself. Do not rethrow an exception using the exception variable that was caught, otherwise object slicing may result.

Function try blocks give you a way to catch any exception that occurs within a function or an associated member initialization list. These are typically only used with derived class constructors.

You should never throw an exception from a destructor.

Finally, exception handling does have a cost. In most cases, code using exceptions will run slightly slower, and the cost of handling an exception is very high. You should only use exceptions to handle exceptional circumstances, not for normal error handling cases (e.g. invalid input).

Chapter quiz

1) Write a Fraction class that has a constructor that takes a numerator and a denominator. If the user passes in a denominator of 0, throw an exception of type std::runtime_error (included in the stdexcept header). In your main program, ask the user to enter two integers. If the Fraction is valid, print the fraction. If the Fraction is invalid, catch a std::exception, and tell the user that they entered an invalid fraction.

Here’s what one run of the program should output:

Enter the numerator: 5
Enter the denominator: 0
Your fraction has an invalid denominator.

Show Solution

15.1 -- Intro to smart pointers and move semantics
14.8 -- Exception dangers and downsides

15 comments to 14.x — Chapter 14 comprehensive quiz

  • Help

    hi Alex,
    I wounder why u put in private int m_numerator = 0; and int m_denominator = 1; while in constructor we already do this they assign any argument Fraction(int numerator = 0, int denominator = 1). Couldn’t i do just say in private int m_numerator; and int m_denominator; or is it any purpose for having both in constructor and assign in private ( cause if we call Fraction f; it still will in constructor put numerator = 0 and denominator = 1) ?

    Thanks in advance!

    • Alex

      The non-static member initializers will be ignored in favor of the ones in the constructor. I included them just as a defensive programming mechanism. In this program, it will never get used. But if we later extended the class, we’d be sure that our numerator and denominator would be initialized to some reasonable value no matter what instead of remaining uninitialized.

  • Daniel

    You are correct. I was copy/pasting on my phone and forgot to update the copy.

    I meant to suggest changing "not ever" to "never".

  • Daniel

    Suggest grammar fix:

    Change: "You should not ever throw an exception from a destructor."

    to: "You should not ever throw an exception from a destructor."

  • Unknown

    When you add topics to rvalue references and semantics

  • aca4life

    After neither my nor your solution compiled I found out that std::exception doesn’t have a string/char* constructor. But since the derived error classes own such a constructor I used std::domain_error from <stdexcept> instead and it worked.

    • Alex

      Interesting, I didn’t realize that a std::exception constructor that took a string was non-standard. I’ll update the code accordingly.

      Doing a little investigation, most developers who want to use a standard exception with a customized error message use std::runtime_error. I’ve updated lesson 14.5 to include a note about this, as well as to fix a few other related issues.

  • Manik

    Can you give tutorials on designing animation programs with c++. I want to make animations with c++. I didn’t understand any line of opengl and directx…

  • aakash gupta

    Hello alex,
    can you give me the code by which the ‘[code’]'[/code’] converts a program to your html-style c++ code.

Leave a Comment

Put C++ code inside [code][/code] tags to use the syntax highlighter