Sign in to follow this  
load_bitmap_file

C++ - 2 unrelated questions

Recommended Posts

(didn't want to create two topics) Question 1: In C++, if something (i.e a function, new, anything) can throw an exception, should you always try to catch it? Question 2: I'm not sure if this is the right forum, but I'm planning on getting either "Design Patterns" or "Modern C++ Design". (I'm short on cash) Both books have very good reviews; I can't decide between the two. "Design Patterns" is supposed to be extremely good for demonstrating proper OOP techniques, but then again "Modern C++ Design" will cover C++ specific stuff like templates... I don't know what to do :[

Share this post


Link to post
Share on other sites
Quote:
Original post by load_bitmap_file
Question 1: In C++, if something (i.e a function, new, anything) can throw an exception, should you always try to catch it?

Usually, yes. Unless you're just going to throw it to the calling function (in which case theres no point catching it and then throwing it again). But you don't want to throw an exception out of main() or WinMain(), since that'll just give you an ugly system message box. At least if you catch it, you can give some more useful information.

As for question 2, I have no idea - I haven't read either of them, sorry.

Share this post


Link to post
Share on other sites


1. If something can throw an exception you should catch it, otherwise if the exception goes unhandled your application will fail. Since C++ (to my knowledge :S) does not support dissociated rethrows.. this is a bad thing as you cannot rethrow the exception if it not handled.

That being said, if you know the only condition that can result in an exception is one that would result in your application failing you can leave it unhandled, but it is not very graceful.

2. Design patterns is a valuable read, and I would choose it first, but I strongly recommend that you get your hands on a copy of Modern C++ Design as soon as you can afford it afterwards.

Share this post


Link to post
Share on other sites
1. Only if you think you can recover from the exception.

2. I actually have Modern C++ Design open in front of me. I haven't read the other book, but Modern C++ Design is absolutely fantastic.

Share this post


Link to post
Share on other sites
1) Depends on what you want to archieve. If you don't catch an exception your program will terminate, if you catch it with a do-nothing-handler your program is propably left in an undefined state.
For most applications undefined is far worse state than terminated.

You can later add handlers to exceptions that you can reasonably handle, it's easy to locate them later. Locating the empty handler that is responsible for some strange behavior might be a lot more difficult.

Share this post


Link to post
Share on other sites
I haven't read Modern C++ design, but this will be my next. Design Patterns is great, told me an awful lot about OOP, but I guess Modern C++ design includes some design patterns as well, so you probably are better off with that for the start.

Thermo

Share this post


Link to post
Share on other sites
Thanks for the replies so far!

Back to question 1: Let's say for example I have this:


class Circle
{
public:
Circle(int x, int y, int radius)
{
/*blah blah other stuff*/

//make sure the radius is valid
if(radius < 0)
throw SomeSortOfException();
}

/*other stuff*/
}

int main()
{
Circle circle1(5, 5, 5);

return 0;
}




As can be seen in the above code segment, every time I run this program the circle1 will be initialized with the same values, and I know that Circle will not throw. Is it a waste of time to stick in a try/catch block here? Obviously it will never throw, but I was wondering if maybe it would be a safeguard incase I decided to change the circle1 values later on or something.

Back to question 2:
It turns out I do have enough money :0 I'm still interested in your opinions though :)

Share this post


Link to post
Share on other sites
Quote:
Original post by load_bitmap_file
(didn't want to create two topics)

Question 1: In C++, if something (i.e a function, new, anything) can throw an exception, should you always try to catch it?
If you know what to do in response to the exception, catch it. Otherwise, let it bubble up until somebody knows how to deal with it. Do NOT do try{func()}catch(...){} unless design specifications force it(which seems to happen frequently because the people that write the requirements don't know how to program at all) or it really doesn't matter if the function fails(which seems to be the case very rarely if at all).

About your above example, you don't need to catch. If somehow you change something and it throws, well it will bubble up and probably 'crash' your program so you'll be notified about the problem (or some user will get the error and be able to report it with line # etc that the CRT hopefully appends)

I don't have either book so I can't help with that.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I have the design patterns book, and have never read the C++ book.

Personally, I'd go with the C++ book. You can probably get by learning about patterns using online resources like this for a while. It's not as good as the book, but it should get you by until you decide to buy the book.

Besides, design patterns are kinda useless unless you know how to program...

But, you should definately get the design pattern books as well if you can.

-HQ.

Share this post


Link to post
Share on other sites
1) With exceptions, there are plenty of articles on GotW in the articles section and the gotw section. A lot of the material there was put into the books Exceptional C++ and More Exceptional C++.

The main thing is, if you can handle the exception and do something reasonable then you should, otherwise let the exception pass you by.

With your example there are a number of things you could do. If someone had supplied you with a negative radius you could ask them to enter a new value. This then would mean the exception was caught and handled at the level of data entry. It is that part of the program which knows what to do.

The function which calls new Circle(x, y, r); probably doesn't know what to do if an exception is thrown. So it's best if it 'does nothing'* and lets the exception leave the function and see whether the function which called it knows what to do, etc, etc.

*'Does nothing' means you have to make sure any other resources will be released correctly. You can sometimes easily do this by using smart pointers. There are plenty of articles, as I said, on GotW. This is probably a good one to start with.

A tempting alternative approach to your example is to say that the radius should be an unsigned int. This would mean it had to be positive. However, as Lakos suggested, unsigned integers shouldn't be put in a public interface as passing a negative signed integer would cause problems which would go undetected.

You could make a simple class called UnsignedInt which would throw an exception if initialised with something negative. Then you create the circle with an UnsignedInt for a radius. This would move the possibility of an exception happening to another place, possibly another function. It may even be possible to put it right at the place the data is entered so you don't get as far as creating the circle but the data is validated at the point of entry. This will mean the program has a far better idea what to do.


//before
Circle* CreateCircle(int x, int y, int r) {
return new Circle(x, y, r);
}

//after
Circle* CreateCircle(int x, int y, int r) {
UnsignedInt radius(r);//could throw
return new Circle(x, y, radius);
}
//or
Circle* CreateCircle(int x, int y, UnsignedInt r) {
return new Circle(x, y, r);
}






Another alternative is to say you'll take the positive of whatever the negative radius is and not flag it as an error

2) Design Patterns is a good book but took me years to get to grips with. This wasn't helped by my superior at work who told me it was rubbish and to not use it. I have found that it makes a lot more sense when combined with Refactoring: Improving the Design of Existing Code. There is a new book called Refactoring to Patterns, which I haven't read but I believe to be good.

The people who first started thinking about patterns in software also set up the first wiki. There is plenty of information, discussion of pros/cons of particular patterns and also of refactoring techniques. It's a good place to start.

Modern C++ Design is a clever book which will stretch your brain cells. If you don't know about design patterns then the motivation for the library which is developed throughout the book may be lost on you. I wouldn't say it's a must read, although when I first read it I thought it was absolutely wonderful.

As I always suggest, if you haven't much money, use price matching sites to get a good deal, club together with friends, or request it from your public library. Design Patterns is probably better to have on your shelf than Modern C++ Design.

Share this post


Link to post
Share on other sites
I agree with Petewood, I think Modern C++ Design has some clever tricks, but a lot of the book will be lost on you if you havn't read Desgin Patterns.

You can look at Modern C++ Design as a book on providing generic implementations in C++ of some of the patterns covered by the Design Patterns book. It has some clever tricks, but depending on your level of C++, a lot of it might be over your head.

I think Design Patterns is a must read for every developer.

Share this post


Link to post
Share on other sites
In your circle example, if the radius is initialised via data in the program rather than user input (or a script file), you would be better off looking at the assert macro (can't remember which header is required). You would do

assert(radius>=0);

which would cause your program to terminate immediately IN DEBUG MODE ONLY. It would have no effect in release mode, hence you catch dodgy data whilst debugging but this has no effect (on program speed, since the check is never performed) when you build a release version.

Share this post


Link to post
Share on other sites
In some case, throwing an exception is more adapted than doing an assert. What if the Circle class is built reading a script or configuration file. You would be happy to be able to output a "The configuration file is ill formated : the radius of a circle must be positive".

You should not catch the exception after calling Circle(5,5,5), because you have in mind that this can't throw. If you don't know the reason of the error, there is no point in handling it because you won't solve the problem.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this