Please use proper indentation for your code. Doing it is a good habit, and most editors have an option that enables automatic indentation. That way we can read your code eaiser. :)
>I thought that catching problems was up to the compiler.
It is, but not entirely. A compiler can only catch syntax errors, not runtime errors. For example, consider the following equation:
x=5/0;
Now, most compilers will automatically alert you of this error because of course, you cannot divide by 0. This is a syntax error. However, consider this statement:
x=5/divider;
The compiler has no way of knowing what divider will contain at runtime. It could have been inputted by the user, been generated as a random number, etc.. There's many other runtime errors that the compiler cannot predict, such as the computer having insufficient memory, a file being missing; you get the idea. So then it's up to your program to handle the errors.
That's where exception handling comes in. It allows you an easy way to control and handle errors, as opposed to the traditional C-style of error checking, where you decided a function's success purely based on return code or values of pointers modified.
You could just throw a simple string, but using classes gives you much more flexibility. You can fill in data such as where the error occured, the date and time, why it occured. Additionally, using classes allows you to take advantage of exception handling's type checking, which will automatically pick out the right catch block to use.