Inheritance can result in low-level code reuse as a side effect, but low-level code reuse can also be gained from composition, sometimes more appropriately than through inheritance. Trying to achieve low-level code reuse via inheritance often results in improper inheritance. For example, deriving Stack from List is an attempt to achieve code reuse via inheritance, and it results in improper inheritance. As suggested, composition is probably a better technique for this situation. In the following example, a Stack object is a composite built from a List object. Thus, class Stack is reusing the code from class List via composition (some or all of these member functions may be virtual; these classes use integers but real stacks and lists would be generic via templates; see FAQ 25-01). class Empty { }; class BadPosition { }; class List { public: void prepend(int item) throw(); void append(int item) throw(); int removeFirst() throw(Empty); int removeLast() throw(Empty); void insertAtPosition(int item, unsigned position) throw(BadPosition); int removeAtPosition(unsigned position) throw(BadPosition,Empty); int& operator[] (unsigned index) throw(BadPosition,Empty); int operator[] (unsigned index) const throw(BadPosition,Empty); unsigned size() const throw(); void setSize(unsigned newSize) throw(); unsigned countMatches(int itemToMatch) const throw(); unsigned findPositionOfMatch(int item) const throw(); protected: // Implementation intentionally omitted }; class Stack { public: void push(int x) throw(); int pop() throw(Empty); int top() const throw(Empty); unsigned size() const throw(); protected: List list_; }; void Stack::push(int x) throw() { list_.append(x); } int Stack::pop() throw(Empty) { return list_.removeLast(); } int Stack::top() const throw(Empty) { return list_[list_.size()-1]; } unsigned Stack::size() const throw() { return list_.size(); } Here is the UML notation for composition: In the following example, a Stack object is a composite built from a List object. |