7.6 Using Map Objects in Error Handling

A map is a simple component that can be used as a part of any error handling or exception handling strategy. A map associates one item with another. For example, a map can be used to associate error numbers with descriptions:

 //... map<int,string> ErrorTable; ErrorTable[123] = "division by zero"; ErrorTable[4556] = "no dial tone"; //... 

Here, the number 123 is associated with "division by zero." If we write:

 cout << ErrorTable[123] << endl; 

Then "division by zero" will be written to cout .

In addition to mapping built-in data types, we may also map user-defined objects with built-in types. Instead of simply returning a message description for each error number, we may return an object with each error number. The object can have methods designed for error correction, error reporting, and error logging. For example, if we have a user -defined object called

 defect_response: class defect_response{ protected:    //...    int DefectNo;    string Explanation; public:    bool operator<(defect_response &X);    virtual int doSomething(void);    string explanation(void);    //... }; 

We can add defect_response objects to the map using something like:

 //... map<int, defect_reponse *> ErrorTable; defect_response * Response; Response = new defect_response; ErrorTable[123] = Response; //... 

This associates a response object with error number 123. Using polymorphism, the map object can contain pointers to any defect_response object or any object that is descended from defect response. For instance, if we have a class:

 class exception_response : public defect_response{    //... public:    int doSomething(void)    //... }; 

called exception_response that is descended from defect_response , then we may also add pointers to type exception_response to the ErrorTable object.

 //... map<int,defect_reponse *> ErrorTable; defect_response * Response; exception_response *Response2; Response = new defect_response; Respone2 = new exception_response; ErrorTable[123] = Response;  // Stores an object of type                                 defect_response ErrorTable[456] = Response2; // Stores an object of type                                 exception_response //... 

This shows that the ErrorTable object can map different objects with different explanations and capabilities with the appropriate error number. Therefore, the references to the doSomething() method:

 //... defect_response *ProblemSolver; ProblemSovler = ErrorTable[123]; ProblemSolver->doSomething(); ProblemSovler = ErrorTable[456]; ProblemSovler->doSomething(); //... 

will each cause the ProblemSolver object to execute a different set of instructions. Although ProblemSolver is a pointer to a defect_response object, polymorphisms allow ProblemSolver to also point to an exception_response object or any other object descended from defect_response . Because the doSomething() method is declared virtual in the defect_response class, the compiler can do dynamic binding. This will ensure that the correct doSomething() method will be called at runtime. This dynamic binding is important because each descendant of defect_response will define its own do-Something() method. We want the doSomething() method to be called based on which descendant of defect_response is referenced. This technique allows us to associate error numbers with objects that are specialized in handling certain error conditions. Using this technique, we can make the error handling code simpler. Example 7.1 shows how the return value from some function can be used to summon the appropriate error handling object:

Example 7.1 Using a function's return values to determine the correct ErrorHandler object to access.
 void importantOperation(void) {    //...    Result = reliableOperation();    if(Result != Success){       defect_response *Solver;       Solver = ErrorTable[Result];       Solver->doSomething();    }    else{       // continue processing    }    //... } 

Notice in Example 7.1 that we do not have a series of if() statements or case statements. The map object allows us to directly access the error handling object we want by index. The doSomething() method called in Example 7.1 will depend on the value of Result . Obviously this is an oversimplification of the processing. For example, Example 7.1 doesn't show who's responsible for memory management of the dynamically allocated objects stored in the ErrorTable map. Also, both the reliableOperation() routine and the doSomething() function might fail. So things can be a little more complicated than what is shown in Example 7.1. However, the example does illustrate how a single piece of code can handle many error situations. We can do better: Example 7.1 assumes that all the errors will be addressed by objects in ErrorTable . The objects in ErrorTable are either defect_response objects or objects descended from defect_response . What if we have multiple families of error handling classes? Example 7.2 shows how we can make the importantOperation() more general using templates.

Example 7.2 Using a template in the importantOperation() function.
 template<class T,class U> int importantOperation(void) {    T ErrorTable;    //...    U *Solver;    //...    Solver = ErrorTable[Result];    Solver->doSomething();    //... }; 

In Example 7.2, ErrorTable is not restricted to defect_response objects. This technique allows us to further simplify and expand the flexibility of our error handling code. This example uses both vertical and horizontal polymorphism. This kind of polymorphism is extremely useful in SPMD and MPMD programs. See Chapter 9 for a discussion on simplifying programs that require concurrency using templates and polymorphism. Using map objects and error handling objects are important steps in the direction of increasing software reliability. We can also take advantage of the exception handling mechanism and the exception handling classes in C++. These facilities add exception handling to error handling techniques.



Parallel and Distributed Programming Using C++
Parallel and Distributed Programming Using C++
ISBN: 0131013769
EAN: 2147483647
Year: 2002
Pages: 133

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net