Chapter 8: Polymorphism and Exceptions
Static binding means that the address of an object is known at compile time. A statically bound function's address is known at compile time. On the other hand, dynamic binding means that a single pointer can point to objects of different types. A dynamically bound function must have its address looked up at run time. A call to a statically bound function results in faster execution than a call to a dynamically bound one.
Once declared virtual in a base class, a member function remains virtual in its derived classes. You do not need to declare a function virtual if the exact type of an object pointer invoking the function is known at compile time.
Destructors are not inherited, so we usually define one for each derived class. Destructors cannot be overloaded because they have no parameters. Destructors can be virtual. A base class should contain a virtual destructor even if the function does nothing.
An abstract class is one that contains at least one pure virtual function. A pure virtual function is a member function that is declared using a pure-specifier, which means the function prototype ends with "= 0". The function must be implemented in any derived class before instances of the class can be created. Pure virtual functions provide a good mechanism to prevent the inadvertent omission of essential operations in dervied classes.
Exception handling is a sophisticated way to handle runtime errors in C++. Rather than aborting a program and leaving objects in an undefined (or corrupted) state, exception handling gives us the ability to perform a more graceful recovery from errors. Exception handling lets us handle an error at different levels, providing context-specific information that can be used as an aid to fixing the problem that caused the exception.
A program throws an exception at the point where an error is first detected. An exception handler responds to the exception by catching the exception. If an appropriate exception handler cannot be found, the program terminates. A try block, introduced by the try keyword, identifies the execution scope of statements that might throw an exception. A try block is always followed by a handler, which begins with the catch keyword.
Most exception handlers identify a specific type of exception that they are able to catch; others can catch any type of exception. Some exception handlers attempt to fix the problem that caused an exception, and then resume the program's execution.
Using the LongArray class, we showed how to detect and handle memory exhaustion, when the new operator failed to allocate storage for an array. An xalloc exception is automatically thrown in such cases.
We also showed how to throw an exception when an array subscript was out of bounds, and we created a custom exception class called RangeError that displayed information about the location where the exception occurred.