Exception handling in C++.

March 9, 2010 at 8:46 pm (C++) (, , , )

I’ve been teaching a course on Data Structures in C++ for the University of Reykjavik. It has been a fun experience for me. I had to write a paper for some students that missed out the part on exception handling, so I thought about sharing it to the world too through my blog.

I will begin this post with a few examples on how to throw and catch errors. After that I will introduce a few classes from the C++ Standard Library that can be easily used. I will make an example class that extends the exception class from the C++ Standard Library and I will use it to throw an error and catch an error with an error message.

Now, let us begin! In C++ you can throw errors of any type. For example:

try
{
    throw 4;                    //int
    throw 3.3;                  //double
    throw false;                //bool
    throw 'c';                  //char
    throw string("test");       //std::string
    throw logic_error("test");  //class
}

And you can also catch an error of any type by using (…) in catch:

try
{
    throw 3.3;
}
catch (...)
{
    cout << "General error of any type" << endl;
}

If you want to throw and catch an error of the type string you would do it in the following way:

try
{
    throw string("I am a string");
}
catch (string s)
{
    cout << s << endl;
}

And as you can see from the example above, you can print the string we grabbed in catch. It would print “I am a string” to the console window. So basically you can throw an object of any type and catch it and use it for whatever reason you want. For example if I want to throw an error of the type integer I would do: throw 3; and if catch would grab an integer, then I would get an integer with the value 3.

Next I’m going to be more specific on how to throw an instance of a class as an error.

In C++ you have access to exception classes in the C++ Standard Library that you can use.
Here below you can see what exception classes are available. They’re indented depending on the inheritance tree.

exception
    logic_error			(extends exception)
        domain_error		(extends logic_error)
        invalid_argument	(extends logic_error)
        length_error		(extends logic_error)
        out_of_range		(extends logic_error)
    runtime_error		(extends exception)
        range_error		(extends runtime_error)
        overflow_error		(extends runtime_error)
        underflow_error		(extends runtime_error)
bad_alloc
bad_cast
bad_exception
bad_typeid

Example:

The class out_of_range extends logic_error and logic_error is a class that extends exception.
Is there a good reason for having all those exception classes available? The main reason is to allow the user to be able to grab a specific error. Let’s assume that we only wanted to grab errors that are instance of the class out_of_range then it would be done in the following way:

try
{
    throw out_of_range("Error message");
}
catch (out_of_range e)
{
    cout << e.what() << endl;
}
catch (...)
{
    cout << "Some error that is not an instance of out_of_range" << endl;
}

If we got an error in the try clause that is not an instance of the class out_of_range, then catch (…) would grab it and print “Some error that is not an instance of out_of_range”.

And if the error was an instance of out_of_range then we would grab it in the catch (out_of_range e) and we would have an access to the function what() within the object e, like shown in the example above.

You may probably be thinking what function is what()? It’s a virtual function that is declared in the base exception class, of which out_of_range extends. It returns a char pointer to the error message supplied in the constructor.

Ok, so now we know how to throw an error that is an instance of a class and how to grab it with catch. Next I’m going to show you how to make your own exception class that extends the exception class in the C++ Standard Library.

In my case, the students were supposed to make an Integer(real number) class that would hold one integer and some function that returns true or false whether the integer is a prime number or not. Thus I will call my new class IntegerException.

I will make IntegerException extend exception, to do that you will need to include iostream and use the namespace std, then the header file for the class will look like the following code:

#include <iostream>
using namespace std;

class IntegerException :
	public exception
{
public:
	IntegerException();
	~IntegerException();
};

Ok great, now since our IntegerException class extends the exception class, then we can make the constructor of our class call the base constructor (the constructor in exception) with the appropriate error message. To do that we need to go to the implementation of our class (usually the .cpp file of the class, IntegerException.cpp) and then add the following to the constructor:

IntegerException::IntegerException() :
    exception("Error message")
{
}

Now our constructor will call the base constructor. The result is that when we call the what() function we will get the error message we supplied to the exception constructor. In this case what() will return a char pointer to “Error message”.

Example usage of the class:

try
{
    throw IntegerException();
}
catch (IntegerException e)
{
    // Here "Error message" will be printed out.
    cout << e.what() << endl;
}

However, now we are stuck with “Error message” every time we throw an error that is an instance of our class IntegerException. What if we want to have a different message depending on where we throw the error? That’s easy, we will just make the constructor of our class take the message as a parameter.

In the example below I will take a char pointer as a parameter and simply let the base constructor have the message:

IntegerException::IntegerException(char* strError) :
    exception(strError)
{
}

You may ask why I use char pointer instead of string as the parameter. That is because the constructor of the exception class wants to have const char *message as the parameter but not string. There’s nothing stopping us from using string, just change it to a char pointer by using the c_str() function in std::string. If we go the string way, the constructor will look like this:

IntegerException::IntegerException(string strError) :
    exception(strError.c_str())
{
}

So now we can throw an error that is an instance of the IntegerException class with any error message you want and we can easily grab it in catch and print out the error message.

Example of usage:

try
{
    throw IntegerException("Error handling is fun");
}
catch (IntegerException e)
{
    // Here "Error handling is fun" will be printed out.
    cout << e.what() << endl;
}

As you can see, exception handling is pretty straight forward. There’s one problem some people have run into, which is when they get divide by zero error. Divide by zero is not detected within the try clause. It was a c++ design decision. So be careful to always check if you divide by zero.

If something is unclear, feel free to comment and ask away 🙂

Thank you for reading!

Advertisements

Permalink 2 Comments

Solving y on a triangle in 3D space given x and z.

November 25, 2009 at 11:53 am (C++) (, , , , )

Yay, my second post.

I’ve been working on a final project at my university, University of Reykjavik for a computer graphics class.
Since I’ve always wanted to create a terrain engine since I was a kiddie, I thought why not? This was my opportunity to do it for once!

The problem I was facing was walking on the surface of the terrain. The y position of the camera was the max of the three points of the triangle I was standing on, which made the movement jerky, like stepping um stairs.

So how can we find the height or the y value for a specific x and z in a triangle? Easy, really! We’ll have to find the equation of a plane from 3 points. But first we need to define two vectors that lie on the plane:

Vector3 is a class of which has three floats; x, y and z.

Vector3 AB(points[1].x – points[0].x, points[1].y – points[0].y, points[1].z – points[0].z);
Vector3 AC(points[2].x – points[0].x, points[2].y – points[0].y, points[2].z – points[0].z);

So now we have two vectors AB and AC, which define a plane from the three points points[0], points[1] and points[2].

Next we’ll have to find the cross product of those two vectors: AB x AC, which will give us the normal vector of the plane.

Vector3 normal(AB.y * AC.z – AB.z * AC.y, AB.z * AC.x – AB.x * AC.z, AB.x * AC.y – AB.y * AC.x);

Normal vector

So now we have the normal vector of the plane. Normal vector is a vector which is perpendicular to the plane.

Next we’ll need to multiply one point of the three points that define the plane with the normal vector to get the equation of the plane.

Basically it’ll give us a number that I call the coefficient:

coefficient =normal.x * points[0].x +normal.y * points[0].y +normal.z * points[0].z;

So now we can get the height for a given x and z in the triangle!

height = (-normal.x*position.x -normal.z * position.z + coefficient) /normal.y;

Reference:
http://www.jtaylor1142001.net/calcjat/Solutions/VPlanes/VP3Pts.htm

Permalink 1 Comment