3

I created a general class that accepts a string when it is constructed, and it spits out that string when a user calls what(). This is all it does; on throw, it returns the initializing string.

class Exception_As {  
private:  
    std::string message  
public:  
    Exception_As(const std::string& message) { // constructor
        this->message ="EXCEPTION: " +message;
    }

    virtual const char* what() const throw() {
        return message.c_str();
    }
}

How I use my custom exception class:

bool check_range(  
    const std::vector<std::string>& list,
    const unsigned& idx_start,  // where to start checking
    const unsigned& idx_end,    // where to stop checking
    const std::string& key
) {
    if ( idx_start > idx_end ) {
        throw Exception_As("check_range: start index > end index: now fix it! :D");
    }

    ... rest of code
} // end of check_range

How a user would use check_range:

// some other user code using my check_range
void main() {
    try {
        ... set up variables

        my_hero_qualified = check_range(semi_finalists, third_place, first_place, my_hero);
        ...rest of code
    }

    catch (const Exception_As& e) {
        std::cout << e.what() << std::endl;
    }
}

If the try/catch was not there, it would abort the program because of the thrown Exception_As. If it was there, the user would be notified that "check_range: start index > end index: now fix it! :D". For me, sure beats writing tons of BadEvent1Exception, BadEvent2Exception, etc classes.

I can see I'm being lazy with this method, and yeah, I can't do anything fancy like modify values based on exceptions or morph an object's state; but if you just entered unexpected territory, who knows if you're handling it correctly? May as well just end it so you can fix what's up and develop properly.

So, question: if all exceptions do is break the program on unexpected circumstances, won't a single exception class that returns the problem be enough?

...Or should exceptions be doing other things anyway? If not, why create so many classes of Exceptions that have different names, sure, but from what I've seen, only report that something went wrong.

2
  • from Joe RounceVille: Could you throw out some code to demonstrate what you're talking about? It sounds like you have some OOAD knowledge gaps, but I hesitate to say that without code that demonstrates what you're saying. Commented Mar 25, 2014 at 21:05
  • No, exceptions can leave your program in an unknown state. And one exception is not like the other.
    – Pieter B
    Commented Mar 27, 2014 at 8:21

4 Answers 4

5

Short answer:

NO

Long answer:

You are getting the concept of exceptions wrong.

Exceptions do not tell the user there's something wrong. It's the calling program that should catch the exception and tell (or not tell) the user something is wrong or recover from it graciously.

If an "exception" has code inside to "fix" something, then it's not an exception by definition.

How can the exception get access to the context of the calling program in order to "fix it"? How does the exception knows the innards of the calling program in order to fix the error?

Also, how can a user call what() after the program aborts? Does the exception also persist the message to a file or database?

Your approach is completely new and unwritten about in books or the web.

Please show us some code.

1
  • changed it up! My exception does nothing, it is up to the catcher to figure out what to do. And that message that says "fix it" would actually show up as "fix it" for the message of the exception. Commented Mar 25, 2014 at 19:27
1

You must distinguish between exceptions for expected error conditions and exceptions that represent bugs in your program.

Let's suppose you've forbidden null in your codebase, or at least within a particular class. If you ever find a null value in one of your private variables, that unambiguously indicates a bug. It's fine to use some generic "something went wrong" exception in cases like these because it should not occur, and if it does, it should go uncaught. That way the application blows up, someone notices there's a bug, and it gets fixed. I recommend throwing an AssertionError or something similar - no one should be catching those, and it clearly expresses that some invariant of your code has been violated.

This is very different from someone calling your method with the wrong arguments, or some outside resource (e.g. files) suddenly vanishing - you know that can and likely will happen. You should provide a reasonably fine-grained exception type so that callers can distinguish different kinds of errors (i.e. don't throw GenericException everywhere).

That said, it's even better if you can write your code such that error states can't happen, or the number of error states are reduced.

1
  • Oh, in terms of logic/implementation/my bugs, I use assertions to stop it from entering/escaping the functions. The exception class I made is strictly for user input. Commented Mar 25, 2014 at 19:29
1

What you have here is the most generic form of Exception, which is only of any real use in a "global" Exception Handler - you know the sort of thing: show a "message" to the user, [hopefully] record the Exception into a file for [your] later diagnostic use, then allow the program to gracefully collapse in a heap, losing everything that the user has done for the last twenty-five minutes.

I regard it as a "backstop", the "Lowest Common Denominator" of Exception "handling" and, whilst it is the way that a lot of people write code, it's not what Exceptions are really about.

An Exception is something that shouldn't normally happen but, by creating an Exception [class] for it, you're acknowledging that it might and, if and when it does, your code is going to react is a pre-defined way (by throwing the Exception).

The calling code has a responsibility to catch the thrown Exception if it can do anything useful with it. That's why we have distinct Exception classes - the "filter" used by Structured Exception Handling schemes are mostly geared-up to figure out what Type of Exception was thrown and, therefore, which "catch" block it should be directed to. This is why Exceptions are "thrown" twice - once to find a handler (and locate any clean-up, "finally" blocks between "here" and "there") and again to actually "throw" it, ready to be handled.

Here's an example:

Method A generates a file name and called Method B, passing that name.

Method B wanders off and tries to store some data in a file of this name in some shared directory, somewhere. But the file name cannot be reused and (for reasons I can't think of currently) Method A has no access to the underlying file system. If Method B is called a second time in, say, the same day, the file will already exist. In this case, Method B cannot overwrite the file without losing data. Instead it throws a "FileAlreadyExists" exception, containing the errant file name.

Without instruction to the contrary, the default Exception Handler, right up at the root of the program (actually up in the Run-Time itself) would catch this (and every other) Exception, show the user an "Oops!" message, and then trash the program. Not altogether useful.

Instead, Method A can catch this Type of Exception and, using the file name that it comes with, compute a new name for the file and try to call Method B again. So long as this attempt doesn't throw another Exception, then the original Exception has been successfully "handled"; the user doesn't need to know anything about it, because the code has dealt with this "unexpected but possible" event.

So, a general-purpose, used-for-everything, "AnyOldException" class isn't much use, because the calling code can't [easily] work out what went wrong (do not try to unpick the Exception's Message property; that way lies Madness). It's far, far better to use a typed Exception and let your code can take the strain.

1
  • Ah, from your example, it seems exceptions should be used for already released code. Because A and B were not originally designed to handle name conflicts, the exception lets users fail with the least amount of "trauma" to the user? Commented Mar 27, 2014 at 16:49
0

Yes: they should state what is wrong & the type of error.

Lets look at a couple of examples for exceptions.

Under C++, if you run out of memory, the new command will throw an exception. This is IMHO a good use. Its something which does happen & you will need to catch & deal with it.

Another exception you might have is an exception thrown if the files you are reading from is incorrectly formatted.

Now lets consider a function which reads from a file & stores it into memory. It could easily throw either of these two exceptions, but they should be handled differently. The bad-format exception can be a simple popup message box. The out-of-memory exception is a much more serious occurrence and should probably save the current state of the program and exit.

If you use the same exception, you cannot tell the two apart, unless you start parsing the string. So in this case I would go for two different exceptions so you can have two different handlers.

So there is a good example of the reason for the various exception types.

1
  • this does not seem to address the question asked: "should exceptions be doing other things anyway?"
    – gnat
    Commented Mar 27, 2014 at 7:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.