Selected C Example 17

 <  Free Open Study  >  

Selected C++ Example #17

 //Example #17  // This example code shows the attempt to implement three // different lists (meal lists, airplane lists, and dog lists) // with one implementation of the list code. The general approach // is to use inheritance to weaken the type-checking mechanism // of C++ by making all data types that want to be in a list // inherit from a common base class (in this case the class // ListItem). The common base class captures any necessary // operations that the LinkedList class might need (in this // case, print() and type()). The problem with weak type // checking is that a wrong derived object might end up on // the wrong list. The benefits of mixed list and strong // type checking are captured in the next example, which // reimplements this code with C++ templates. // This example could be extended to include type checking. // The algorithm for doing this is to have each LinkedList // object remember the data type of the first argument inserted. // Once this is recorded all other insertions will check the // type of the object being added to the list with the stored // value. Of course, this algorithm makes it impossible to // have mixed data type lists anywhere in the application. #include <iostream.h> #include <new.h> // ListItem is the class responsible for weakening the type // checking of C++. We make all of our list element classes // inherit from this common base class. The LinkedList will // be of pointers to this base class. Note that all ListItems // must know how to give their type and print themselves. class ListItem { public:      virtual void print(ostream& o = cout) = 0;      virtual const char* type() = 0; }; // The derived classes Dog, Meal, and Airplane are only // skeleton classes to simplify their implementation. class Dog : public ListItem { public:      void bark();      void bite();      void print(ostream&o = cout);      const char* type(); }; void Dog::bark() {      cout << ''Bow Wow\n''; } void Dog::bite() {      cout << ''Ouch!!!\n''; } void Dog::print(ostream& o) {      o << ''I am a dog!\n''; } const char* Dog::type() {       return(''Dog''); } class Meal : public ListItem { public:      void eat();      void print(ostream& o = cout);      const char* type(); }; void Meal::eat() {      cout << ''Crunch ... Munch ... Crunch ... \n''; } void Meal::print(ostream& o) {      o << ''I'm a meal\n''; } const char* Meal::type() {      return(''Meal''); } class Airplane : public ListItem { public:       void fly();       void print(ostream& o = cout);       const char* type(); }; void Airplane::fly() {      cout << ''Va-a-a--room!!!\n''; } void Airplane::print(ostream& o) {      o << ''I'm an airplane!\n''; } const char* Airplane::type() {      return(''Airplane''); } typedef ListItem* DATUM; class LinkedList {      struct Node {          DATUM data;          Node* next;      public:          Node(DATUM&);      };      Node* head;      int len; public:      LinkedList();      ~LinkedList();      int insert(DATUM&);      DATUM remove();      void traverse()const;      int length(); }; LinkedList::Node::Node(DATUM& new_data) {      data = new_data;      next = NULL; } LinkedList::LinkedList() {      head = NULL;      len = 0; } LinkedList::~LinkedList() {      Node* temp;      while (head != NULL) {          temp = head;          head = head->next;          delete temp;      } } int LinkedList::insert(DATUM& new_item) {      Node* temp = head;      if (temp == NULL) {           head = new Node(new_item);      }      else {           while (temp->next != NULL) {                      temp = temp->next;           }           temp->next = new Node(new_item);      }      return(++len); } // The remove method needs something to return if the list // is empty. We deal with this problem by creating a dummy // DATUM as an internal variable within the remove method. DATUM LinkedList::remove() {      Node* temp = head;      static DATUM bad_item;      DATUM retval;      if (temp == NULL) {           return(bad_item);      }      else {           retval = head->data;           head = head->next;           len--;           delete temp;           return(retval);      } } // Notice that the traverse method sends a message to the // data in each node to print itself. This sets up a requirement // that any data type that wants to be in a LinkedList needs // a print method (this constraint is enforced in the base // class ''ListItem''). An even more important consideration is // the fact that the syntax is different if DATUM is a pointer // or nonpointer. Nonpointers would use a dot, and not // an arrow, operator. This problem carries over to templates // as well. It is common to see templates advertise which types // they can, and cannot, handle. void LinkedList::traverse() const {      Node* temp = head;      cout << ''(\n'';      while (temp != NULL) {          temp->data->print();          cout << ''\n'';          temp = temp->next;      }      cout << '')\n\n''; } int LinkedList::length() {      return(len); } void main() {      LinkedList MealList, AirplaneList, DogList;      Meal *meal1 = new Meal, *meal2 = new Meal, *meal3 = new Meal;      Dog *dog1 = new Dog, *dog2 = new Dog, *dog3 = new Dog;      Airplane *air1 = new Airplane, *air2 = new Airplane, *air3 = new Airplane; // At first glance everything seems to work nicely.       MealList.insert(meal1);       MealList.insert(meal2);       MealList.insert(meal3);       Meal* aMeal = (Meal*) MealList.remove();       aMeal->eat();       AirplaneList.insert(air1);       AirplaneList.insert(air2);       AirplaneList.insert(air3);       DogList.insert(dog1);       DogList.insert(dog2);       DogList.insert(dog3);       MealList.traverse();       AirplaneList.traverse();       DogList.traverse(); // Until we see some of the nasty side effects of weak type // checking. This code accidentally flies a dog off the // runway at the airport.       AirplaneList.insert(dog2);       DATUM anItem;       while (AirplaneList.length() != 0){           anItem = AirplaneList.remove();           cout << ''My real type is '' << anltem->type() << ''\n'';           cout << ''I can fly. . .watch. . . \n'';           ((Airplane*) anItem)->fly();       }       delete meal1;       delete meal2;       delete meal3;       delete dogl;       delete dog2;       delete dog3;       delete air1;       delete air2;       delete air3; } 
 <  Free Open Study  >  


Object-Oriented Design Heuristics
Object-Oriented Design Heuristics (paperback)
ISBN: 0321774965
EAN: 2147483647
Year: 1996
Pages: 180

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