GCO4020/CSC428 - Advanced Object Oriented Techniques In C++
Week 4

 

Topic 8: Wrappers

Solutions to Exercises


Synopsis


Solution to Exercise 1

There are several advantages in providing a wrapped Stack class, rather than using a "raw" Array:

  1. By restricting the public interface¤, the Stack class enforces the "last-in-first-out" semantics of a stack, ensuring that elements beneath the top element cannot be "accidentally" accessed out of turn.

  2. If stacks are to be used often, the Stack class can actually reduce code size, since every "pop" of a "raw array" would require (at least) two statements: an operator[] on the last element of the array, followed by a RemoveLast().

  3. By encapsulating such sequences of statements, we also ensure that one step in the sequence is not accidentally omitted somewhere, creating a hard-to-find bug in the program.

  4. It is easy to alter the implementation¤ of the Stack class (for example, to replace class Array with one of the STL¤ classes, say deque)

(End of solution)  
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


Solution to Exercise 2

There are several possible situtaions in which encapsulation¤ and not inheritance is the correct solution:

  1. When the implementation¤ of a wrapper is a built-in type (in which case it is not possible to inherit from it). For example, a Date wrapper class might be implemented by encapsulating an unsigned int or unsigned long.

  2. When the correct implementation¤ requires two or more of a particular implementation¤ type. For example a PriorityStack might require two arrays, corresponding to "high" and "low" priority items.

  3. In the rare case that the appropriate implementation¤ class¤ is not designed to be inherited from (for example, see "Sidebar: Preventing Inheritance").

(End of solution)  
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


Solution to Exercise 3

The only errors which can occur in the operation of the stack are attempts to call Stack::Top() or Stack::Pop() when the stack is empty. But both these attempts will result in Array::operator[] being called with an invalid (negative) index, which will in turn result in an Array::BoundsError exception being thrown. In other words, both versions of Stack "inherit" the error handling behaviour of their underlying Array implementation¤.

Of course, it may be considered desirable in the inheritance version to make Array::BoundsError publicly (not privately) accessible in Stack (that is, provide another using declaration), so as to be able to write:

template <class ElementType> class Stack : private Array<ElementType> { public: using Array<ElementType>::Count; using Array<ElementType>::BoundsError;

void Push(const ElementType& elem);

const ElementType& Top(void) const;

ElementType Pop(void); };

Stack<int> stack;

try { stack.Pop } catch (Stack<int>::BoundsError error) { // HANDLE EXCEPTION }

rather than being forced to catch an Array<int>::BoundsError.

 


This material is part of the GCO4020/CSC428 - Advanced Object Oriented Techniques In C++ course.
Copyright © Damian Conway, 1997. All rights reserved.

Last updated: Fri Feb 18 11:17:31 2000