Eco Simulation  «Prev  Next»
Lesson 8

Simulation Program Conclusion

In this module, you examined the design and code of a simple ecological simulation program that is an extension of the predator simulation program used as the course project in Building Classes in C++.
In particular, you examined:
  1. the abstract base class for the lifeforms in the ecological simulation
  2. the lifeform inheritance hierarchy
  3. the lifeform interaction rules
  4. how the simulation is initialized and displayed

Generic Programming with Inheritance and Templates

If you read the description of the ITERATOR pattern in [2], you will find another recommendation that we omitted from our pattern. The authors suggest using abstract base classes for the iterator and aggregate, so that the client does not have to know about the exact types of the iterator and aggregate. A client can then write generic code such as the following:
void print_all(AbstractAggregate* items){
  AbstractIterator* iter = items->create_iterator();
  while (!iter->is_done()){
    cout << iter->current_item() << "\n";
    iter->next();
  }
}

This function can be used to print items of any derived class of AbstractAggregate. For example, if there are list and array classes that both inherit from AbstractAggregate, then the virtual create_iterator function returns an appropriate iterator that belongs to some derived class of AbstractIterator. The implementations for list iterators and array iterators will be very different, but the client will notknow or care. The virtual functions is_done, current_item, and next automatically invoke the appropriate functionality of the iterator objects.
In some programming languages"in particular Java and Smalltalk" this style of iteration is very common. There are also C++ libraries whose aggregate and iterator classes derive from common base classes. However, the standard C++ library uses templates, not inheritance, to achieve genericity. Using templates is more efficient because it avoids the cost of virtual function calls. With the standard C++ library, we implement print_all as a function template. A template parameter denotes an arbitrary container.
template< typename T>
void print_all(const T& items)
{
T::iterator iter = items.begin();
while (iter != items.end())
{
cout << *iter << "\n";
iter++;
}
}

There is no inheritance at work. For the template to compile, T must be a type that has begin() and end() functions and a nested type called iterator. That iterator type must have operators !=, *, and ++. If the function is called with an inappropriate type, then the compiler reports an error.