Exception handling

closed account (jvqpDjzh)
Is my code good?
Of course, the example is trivial and stupid..
Suggestions to improve it?
Thank you in advance!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
//example2: class that defines the type of the error
class OverSpeed : public exception
{
	const int speed;
	char* message = NULL;


public:

	OverSpeed( int limit ) : 
		speed ( limit )
	{	
		message = "OVER SPEED!";
	}
	
	const char* what( ) const
	{
		return message;
	}
	
	int getSpeed( ) const
	{
		return speed;
	}
};
//
//
//class that handles the error
class Car
{
	int speed;
	int acceleration;
	OverSpeed os;

	const int limit;

public:

	//constructor: initialize the speed
	Car( int speed, const int limit ) : os( speed ), limit( limit )
	{
		try {
			if (speed > limit || speed < 0)
				throw os;
			else
				this->speed = speed;
		} catch ( OverSpeed ex ) {
			cout << "ERROR: " << ex.what( ) << endl;
		}
	}

	//calculates the acceleration
	void accelarate(int seconds)
	{
		(seconds > 0) ? (acceleration = speed / seconds) : acceleration = 0;
	}

};


//in the main function
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main(int argc, char** argv)
{
	int speed, limit;

	cout << "Let's create a car...\n";
	cout << "Choose the the speed limit: ";
	cin >> limit;
	cout << "Choose the actual speed: ";
	cin >> speed;

	Car car1( speed, limit );

	//system( "pause" );
	return 0;
}
Last edited on
Exception types should use virtual inheritance when deriving from other exception types. This insight is due to Andrew Koenig. Using virtual inheritance prevents ambiguity problems in the exception handler
http://www.boost.org/doc/libs/1_55_0/libs/exception/doc/using_virtual_inheritance_in_exception_types.html

Throw by Value, Catch by Reference - Sutter and Alexandrescu in 'C++ Coding Standards: 101 Rules, Guidelines, and Best Practices'
http://www.informit.com/articles/article.aspx?p=373339
Throwing and catching an exception in the same place is not good idea at all. Using exception for non-exceptional situations too.

You should not use exceptions as flow control.
Your example is not doing what you want: even if you enter invalid speed, Car instance will be created and rest of the progra would not know about invalid state.

You should not create new exception types except in some rare cases, exception description is where you want to place error description.

You should catch exceptions by reference, not value to prevent slicing and preserve real exception type.
closed account (jvqpDjzh)
@MiiNiPaa wrote:
Your example is not doing what you want: even if you enter invalid speed, Car instance will be created and rest of the progra would not know about invalid state.

So I sould use the try/catch construct in the main, for example?
//outside the main
1
2
3
4
5
6
7
//outside the main
	//constructor: initialize the speed
	Car( int speed, const int limit ) : os( speed ), limit( limit )
	{
		if (speed > limit || speed < 0) throw os;
		else this->speed = speed;
	}


1
2
3
4
5
6
7
8
#include "OverSpeed.h"
//in the main:

	try {//in this case if the exception is thrown the car is not created, right?
                Car car1(200, 100);
	} catch ( OverSpeed &ex ) {
		cout << "ERROR: " << ex.what( ) << endl;
	}


//suggestions?
closed account (jvqpDjzh)
@MiiNiPaa wrote:
not value to prevent slicing and preserve real exception type.
I didn't understand it quite enough...
I'm not 100% on this, but I really wouldn't suggest throwing your class object. It may be better to try and gather a certain input, if that input is not valid, throw a certain enumerated exception.

With exceptions you want to try and avoid giving the user an opportunity to input invalid data. The idea of an exception is to catch invalid data to prevent a bad program state.

You could even try to make a separate method to read your speed and other member variables to prevent data being corrupted.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
enum Exceptions {OUTOFBOUNDS};

	const Array::operator [] (int i) const
	{
		if (!(IsValidSubscript (i)))
			 throw OUTOFBOUNDS;
		return pData[i - L];
	}


	bool Array::IsValidSubscript (const int i) const
	{
			if ((i >= L) && (i <= U))
				return true;
			else
				return false;
	}


By doing something like this with an array, you prevent the user from accessing an invalid index of the array. You can try to implement something of the same logic in your program with your member variables
Last edited on
I didn't understand it quite enough...

http://ideone.com/iu8BHh
Example of slicing. Note that two catch blocks outputs different lines because of catching by value in first case.

wouldn't suggest throwing your class object.
And I would suggest to throw classes. You will get benefits of inheritance, can hold nessesary info for exception handler and can wrap all manipulations in itself.
So I sould use the try/catch construct in the main, for example?

The problem here is one that you are already aware of, this example is a little too trivial. You're trying to use exception handling where input validation belongs. In the real world with something like this you wouldn't exit your constructor, you would instead prompt the user to reenter valid input.

A better example would be something like running out of memory or disconnecting from a data source. Say you had a program that should grab 'X' number of data samples, perform some operation on the set, and then write the result to the disk. But for some reason the system runs out of memory before you reach 'X' or your system loses it's network connection or the program was told to shutdown unexpectedly. In this case you could throw an exception to interrupt the programs execution, process what you have and then write the result to the disk while probably popping a message up for the user then go do what you think is necessary (die, attempt to reconnect etc.). Keep in mind that exceptions aren't mandatory for every program, they are a design consideration.
Topic archived. No new replies allowed.