// file: uml2.cc // author: keller // RCS: $Id: uml2.cc,v 1.3 2000/02/07 20:50:48 keller Exp $ // // purpose: modeling the following UML class diagram // // .---------------. .---------------. // . Building .<*>----------. Room . // .---------------. * .---------------. // . . . number . // . . . length . // . . . width . // .---------------. .---------------. // . addRoom() . . . // .---------------. .---------------. // /-\ // | // | // | // ---------------------------------------- // | | // | | // | | // .---------------. .---------------. // . Classroom . . Office . // .---------------. .---------------. // . occupant . // .---------------. // // where <*> is supposed to be a filled-in diamond (composition> // and /-\ is supposed to be an open triangle (inheritance) // // Note: For purposes of exposition and conciseness, we do not use separate // header files, etc., nor do we include all constructors, destructors, // and assignment operators. #include // the STL list template #include // the STL string class class Building; // forward declaration /////////////////////////////////////////////////////////////////////////////// // A Room is in a Building. // It has a number, length, and width. // It knows its building. // This class is abstract; we only directly create specific types of rooms. /////////////////////////////////////////////////////////////////////////////// class Room { protected: Building *building; // the building containing this room int number; // the room number of this room int length; // the length of the room in feet int width; // the width of the room in feet public: // create a room in a building Room(Building *building, int number, int length, int width) { this->building = building; this->number = number; this->length = length; this->width = width; } // print a description of the room, including the type of room // If this were not declared 'virtual', then calling the method of this name // would always use the one in the base class, rather than in the derived // class which might over-ride it. virtual void show(ostream &out) { out << "room " << number << " " << length << "x" << width << " " << type() << endl; } virtual string type() = 0; // pure virtual method // (causes class to be abstract) // Without a virtual type method, we would // have no right to refer to specialize // the type to the derived classes. virtual ~Room() // virtual destructor { } }; /////////////////////////////////////////////////////////////////////////////// // A Classroom is a kind of Room. /////////////////////////////////////////////////////////////////////////////// class Classroom : public Room { public: // create a classroom in a building Classroom(Building *building, int number, int length, int width) : Room(building, number, length, width) { } string type() { return "classroom"; } }; /////////////////////////////////////////////////////////////////////////////// // An Office is a kind of Room. // It has an occupant. /////////////////////////////////////////////////////////////////////////////// class Office : public Room { private: string occupant; public: // Create an office in a building for a specific occupant. Office(Building *building, int number, int length, int width, string occupant) : Room(building, number, length, width) { this->occupant = occupant; } string type() { return "office"; } // print a description of the room, including the type of room and occupant // (over-rides show in the base class) void show(ostream &out) { out << "room " << number << " " << length << "x" << width << " " << type() << " " << occupant << endl; } }; /////////////////////////////////////////////////////////////////////////////// // A Building has a set of rooms. // Each is on a particular floor. /////////////////////////////////////////////////////////////////////////////// class Building { private: list rooms; // the rooms in the building public: // create a classroom in the building void addClassroom(int number, int floor, int length, int width) { Room *theNewRoom = new Classroom(this, number, length, width); rooms.push_back(theNewRoom); } // create an office in the building void addOffice(int number, int floor, int length, int width, string occupant) { Room *theNewRoom = new Office(this, number, length, width, occupant); rooms.push_back(theNewRoom); } // show the contents of the building void show(ostream &out) { list::iterator p; for( p = rooms.begin(); p != rooms.end(); ++p ) { (*p)->show(out); } } }; main() { Building b; b.addClassroom(101, 1, 10, 20); b.addClassroom(102, 1, 15, 30); b.addClassroom(201, 2, 20, 25); b.addClassroom(301, 3, 30, 50); b.addOffice(202, 2, 10, 20, "alice"); b.addOffice(204, 2, 10, 20, "dilbert"); b.show(cout); } /* output: room 101 10x20 classroom room 102 15x30 classroom room 201 20x25 classroom room 301 30x50 classroom room 202 10x20 office alice room 204 10x20 office dilbert If the show method in the base class were not virtual, we would instead get: room 101 10x20 classroom room 102 15x30 classroom room 201 20x25 classroom room 301 30x50 classroom room 202 10x20 office room 204 10x20 office */