Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com
Answertopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

Thinking in C++ Vol 2 - Practical Programming
Prev Home Next

Exception matching

When an exception is thrown, the exception-handling system looks through the nearest handlers in the order they appear in the source code. When it finds a match, the exception is considered handled and no further searching occurs.

Matching an exception doesn t require a perfect correlation between the exception and its handler. An object or reference to a derived-class object will match a handler for the base class. (However, if the handler is for an object rather than a reference, the exception object is sliced truncated to the base type as it is passed to the handler. This does no damage, but loses all the derived-type information.) For this reason, as well as to avoid making yet another copy of the exception object, it is always better to catch an exception by reference instead of by value.[3] If a pointer is thrown, the usual standard pointer conversions are used to match the exception. However, no automatic type conversions are used to convert from one exception type to another in the process of matching. For example:

//: C01:Autoexcp.cpp
// No matching conversions.
#include <iostream>
using namespace std;
 
class Except1 {};
 
class Except2 {
public:
Except2(const Except1&) {}
};
 
void f() { throw Except1(); }
 
int main() {
try { f();
} catch(Except2&) {
cout << "inside catch(Except2)" << endl;
} catch(Except1&) {
cout << "inside catch(Except1)" << endl;
}
} ///:~
 

Even though you might think the first handler could be matched by converting an Except1 object into an Except2 using the converting constructor, the system will not perform such a conversion during exception handling, and you ll end up at the Except1 handler.

The following example shows how a base-class handler can catch a derived-class exception:

//: C01:Basexcpt.cpp
// Exception hierarchies.
#include <iostream>
using namespace std;
 
class X {
public:
class Trouble {};
class Small : public Trouble {};
class Big : public Trouble {};
void f() { throw Big(); }
};
 
int main() {
X x;
try {
x.f();
} catch(X::Trouble&) {
cout << "caught Trouble" << endl;
// Hidden by previous handler:
} catch(X::Small&) {
cout << "caught Small Trouble" << endl;
} catch(X::Big&) {
cout << "caught Big Trouble" << endl;
}
} ///:~
 

Here, the exception-handling mechanism will always match a Trouble object, or anything that is a Trouble (through public inheritance),[4] to the first handler. That means the second and third handlers are never called because the first one captures them all. It makes more sense to catch the derived types first and put the base type at the end to catch anything less specific.

Notice that these examples catch exceptions by reference, although for these classes it isn t important because there are no additional members in the derived classes, and there are no argument identifiers in the handlers anyway. You ll usually want to use reference arguments rather than value arguments in your handlers to avoid slicing off information.

Thinking in C++ Vol 2 - Practical Programming
Prev Home Next

 
 
   Reproduced courtesy of Bruce Eckel, MindView, Inc. Design by Interspire