CS 202 Fall 2013  >  Notes for Thursday, October 31, 2013

CS 202 Fall 2013
Notes for Thursday, October 31, 2013

Exceptions (cont'd) [16.1]

Standard Exception Types

The C++ Standard Library defines a number of exception types. All of these are derived from base class std::exception. Most of the derived types are declared in standard header <stdexcept>. See documentation for the C++ Standard Library for more information on standard exception types.

You may define and use your own exception types. If you wish, you may make these derived classes of standard exception types (all of which have virtual destructors).

[C++]

#include <exception>
using std::exception;

class UphappyWidget : public exception {
    ~~~
};

Throwing

Last time we caught exceptions. We can also throw them. We do this when our code encounters an error condition that it cannot handle. When we throw an exception to signal the caller that there is something amiss.

[C++]

~~~
if (widget.is_unhappy())
{
    throw UnhappyWidget();
}
~~~

Note that when we write a throw statement, we are passing an error condition on to some other code. Usually someone else writes the catch blocks. We almost never write both a throw and a catch.

Catch-All & Re-Throw

We can catch all exceptions by putting “...” inside the parentheses after catch. In this case, we do not get to look at the exception object.

[C++]

catch (...)

Inside a catch block, we can re-throw the same exception using throw with no parameters.

[C++]

throw;

The above two features of C++ are almost always used together. Suppose we make a function call that might throw. If it does, we cannot handle the error, but we need to do some clean-up work before passing the exception on to our caller. In this case, we call the function inside a try block, then catch-all, do the clean-up, and re-throw.

[C++]

~~~
try
{
    foo();       // Might throw
}
catch (...)      // Catch-all
{
    clean_up();  // Whatever we need to do
    throw;       // We cannot handle the error here; send it on
}
~~~

Throwing & Catching: Philosophy

We use an exception to signal an error condition. Thus:

As noted above, we almost never write both a throw and a catch (except when we do catch-all & re-throw). Rather, it is often the author of a package who writes a throw statatement to inform the caller that the package has an error it cannot handle. And it is often the author of code that uses a package who writes a catch block to handle an error enountered in the package.

This also explains why it is a good idea to indicate the kind of error by the type of the object thrown. We catch an exception by its type. We catch a certain type when we can handle the kind of error it signals.

As stated last time, I recommend that you catch exceptions by reference.

[C++]

try
{
    ~~~
}
catch (std::runtime_error & e)  // "&" for catch by reference
{
    ~~~

There are two reasons for this.

Function Templates [16.2]

Introduction to Templates

A C++ template is a way of writing code that does not specify what types it is used with. Templates enable generic programming, in which we write data structures and algorithms that can handle arbitrary types of data.

A class template tells the compiler how to write a class using some type that the compiler figures out. Using such a template, the compiler can write one or more actual classes. For example, vector is a class template, while vector<int> is a class that a compiler can write based on the vector template.

Now we look at function templates, which allow compilers to write functions in a similar manner.

Writing Function Templates

Here is a function that prints an int with a message.

[C++]

void likeBetter(int n, int x)
{
    cout << "Here is something I like " << n
         << " times as much as I like you: "
         << x << endl;
    int xx = x + x;
    cout << "And here is what I get when I add it to itself: "
         << xx << endl;
}

We can call the above function passing a double for x, but this will convert the double to an int. If we do not want this to happen, we could overload the function with a separate double version.

[C++]

void likeBetter(int n, double x)
{
    cout << "Here is something I like " << n
         << " times as much as I like you: "
         << x << endl;
    double xx = x + x;
    cout << "And here is what I get when I add it to itself: "
         << xx << endl;
}

And then we could write another version for a string or any other type.

Using a function template we can write all of these at once.

[C++]

template<typename PrintType>
void likeBetter(int n, PrintType x)
{
    cout << "Here is something I like " << n
         << " times as much as I like you: "
         << x << endl;
    PrintType xx = x + x;
    cout << "And here is what I get when I add it to itself: "
         << xx << endl;
}

Here, PrintType is a template parameter. It is a type that the compiler gets to choose.

Note that we do not change every instance of int to PrintType, but only the ones we want the compiler to choose.

Calling Function Templates

We call a function template just like an ordinary function. The compiler determines what to do with the template parameters and writes the required function based on the template.

[C++]

int x1 = 42;
likeBetter(3, x1);
string x2 = "chocolate ice cream";
likeBetter(100, x2);

Overloading with Ordinary Functions

We can write an ordinary function that will be used in preference to a template when the parameter types match.

[C++]

void likeBetter(int n, double x)
{
    cout << "Here is a FLOATING-POINT NUMBER I like " << n
         << " times as much as I like you: "
         << x << endl;
    double xx = x + x;
    cout << "And here is what I get when I add it to itself: "
         << xx << endl;
    cout << "WOW!!!!!!!!!!!!!!!!!!!!!!" <<endl;
}

Now we can call both template and non-template versions using different parameter types.

[C++]

int x1 = 42;
likeBetter(3, x1);  // Calls template version
double x3 = 3.7;
likeBetter(4, x3);  // Calls non-template version

See functemp.cpp for a program that includes a function template.

For today’s lab work, see the 10/31 Challenge.


CS 202 Fall 2013: Notes for Thursday, October 31, 2013 / Updated: 31 Oct 2013 / Glenn G. Chappell