Instead of throwing exceptions of pre-defined types like int, float, char, etc., we can create classes and throw those class types as exceptions. Empty classes are particularly useful in exception handling. Following program demonstrates throwing class types as exceptions:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include<iostream> using namespace std; class ZeroError {}; void sum() { int a, b; cout << "Enter a and b values: "; cin >> a >> b; if (a == 0 || b == 0) throw ZeroError(); else cout << "Sum is: " << (a + b); } int main() { try { sum(); } catch (ZeroError e) { cout << "a or b cannot be zero"; } return 0; } |
Input and output for the above program is as follows:
1 2 3 4 | Enter a and b values: 0 8 a or b cannot be zero |
In the above program ZeroError is an empty class created for handling exception.
Exception Handling and Inheritance
In inheritance, while throwing exceptions of derived classes, care should be taken that catch blocks with base type should be written after the catch block with derived type. Otherwise, the catch block with base type catches the exceptions of derived class types too. Consider the following example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #include<iostream> using namespace std; class Base {}; class Derived: public Base {}; int main() { try { throw Derived(); } catch (Base b) { cout << "Base object caught"; } catch (Derived d) { cout << "Derived object caught"; } return 0; } |
Output for the above program is as follows:
1 2 3 | Base object caught |
You can see that in the above program even though the exception thrown is of the type Derived it is caught by the catch block of the type Base. To avoid that we have to write the catch block of Basetype at last in the sequence as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #include<iostream> using namespace std; class Base {}; class Derived: public Base {}; int main() { try { throw Derived(); } catch (Derived d) { cout << "Derived object caught"; } catch (Base b) { cout << "Base object caught"; } return 0; } |
Output of the above program is as follows:
1 2 3 | Derived object caught |
Exceptions in Constructors and Destructors
It is possible that exceptions might raise in a constructor or destructors. If an exception is raised in a constructor, memory might be allocated to some data members and might not be allocated for others. This might lead to memory leakage problem as the program stops and the memory for data members stays alive in the RAM.
Similarly, when an exception is raised in a destructor, memory might not be deallocated which may again lead to memory leakage problem. So, it is better to provide exception handling within the constructor and destructor to avoid such problems. Following program demonstrates handling exceptions in a constructor and destructor
Take your time to comment on this article.