1 Object-Oriented Design Inheritance and Class Examples
2 Inheritance Example -- Class.zip One reason to use inheritance is that it permits you to reuse code from a previous project, but gives you the flexibility to slightly modify it if the old code doesn't do exactly what you need for the new project. It doesn't make sense to start every new project from scratch since some code will certainly be repeated in several programs and you should strive to build on what you did previously.
3 INHERITANCE A SIMPLE CLASS TO START WITH Example program > VEHICLE.H
4 VEHICLE.H It consists of four simple methods which can be used to manipulate data pertaining to our vehicle. We will eventually refer to this as a base class or parent class.
5 THE IMPLEMENTATION FOR VEHICLE Example program > VEHICLE.CPP The initialize() method assigns the values input as parameters to the wheels and weight variables. We have methods to return the number of wheels and the weight, and finally, we have one that does a trivial calculation to return the loading on each wheel.
6 USING THE VEHICLE CLASS Example program > TRANSPRT.CPP Inheritance uses an existing class and adds functionality to it to accomplish another, possibly more complex job. It declares four objects of the vehicle class, initializes them, and prints out a few of the data values to illustrate that the vehicle class can be used as a simple class because it is a simple class. We are referring to it as a simple class as opposed to calling it a base class or derived class as we will do next.
7 OUR FIRST DERIVED CLASS Example program > CAR.H The vehicle class is inherited due to the ": public vehicle" added to line 7. This derived class named car is composed of all of the information included in the base class vehicle, and all of its own additional information. Even though we did nothing to the class named vehicle, we made it into a base class because of the way we are using it here.
8 To go a step further, even though it will be used as a base class in an example program later, there is no reason it cannot continue to be used as a simple class in the previous example program. In fact, it can be used as a simple class and a base class in the same program. The question of whether it is a simple class or a base class is answered by the way it is used. OUR FIRST DERIVED CLASS Example program > CAR.H
9 In this case, the vehicle base class can be used to declare objects that represent trucks, cars, bicycles, or any number of other vehicles you can think up. The class named car however can only be used to declare an object that is of type car because we have limited the kinds of data that can be intelligently used with it. The car class is therefore more restrictive and specific than the vehicle class. The vehicle class is more general than the car class. OUR FIRST DERIVED CLASS Example program > CAR.H
10 If we wished to get even more specific, we could define a derived class using car as the base class, name it sports_car, and include such information as red_line_limit for the tachometer which would be silly for the family station wagon. The car class would therefore be used as a derived class and a base class at the same time, so it should be clear that these names refer to how a class is used. OUR FIRST DERIVED CLASS Example program > CAR.H
11 HOW DO WE DECLARE A DERIVED CLASS? A derived class is defined by including the header file for the base class as is done in line 5, then the name of the base class is given following the name of the derived class separated by a colon as is illustrated in line 7. All objects declared as being of class car therefore are composed of the two variables from the class vehicle because they inherit those variables, and the single variable declared in the class car named passenger_load.
12 An object of this class will have three of the four methods of vehicle and the two new ones declared here. The method named initialize() which is part of the vehicle class will not be available here because it is hidden by the local version of initialize() which is a part of the car class. The local method will be used if the name is repeated allowing you to customize your new class. HOW DO WE DECLARE A DERIVED CLASS?
13 A Graphical Representation of an object of this class.
14 Information Hiding Note that the implementation for the base class only needs to be supplied in its compiled form. The source code for the implementation can be hidden for economic reasons to aid software developers. Hiding the source code also allows the practice of information hiding. The header for the base class must be available as a text file since the class definitions are required in order to use the class.
15 THE CAR CLASS IMPLEMENTATION Example program > CAR.CPP The first thing you should notice is that this file has no indication of the fact that it is a derived class of any other file, that can only be determined by inspecting the header file for the class. Since we can't tell if it is a derived class or not, it is written in exactly the same way as any other class implementation file.
16 ANOTHER DERIVED CLASS Example program > TRUCK.H This class adds two more variables and three more methods. A very important point that must be made is that the car class and the truck class have absolutely nothing to do with each other, they only happen to be derived classes of the same base class or parent class as it is sometimes called.
17 A Graphical Representation of the truck class
18 Note that both the car and the truck classes have methods named passengers() but this causes no problems and is perfectly acceptable. If classes are related in some way, and they certainly are if they are both derived classes of a common base class, you would expect them to be doing somewhat similar things. In this situation there is a good possibility that a method name would be repeated in both child classes. Example program > TRUCK.H
19 THE TRUCK IMPLEMENTATION Example program > TRUCK.CPP Examine the file named TRUCK.CPP for the implementation of the truck class. It has nothing unusual included in it.
20 USING ALL THREE CLASSES Example program > ALLVEHIC.CPP It uses the parent class vehicle to declare objects and also uses the two child classes to declare objects. This was done to illustrate that all three classes can be used in a single program.
21 Example program > ALLVEHIC.CPP All three of the header files for the classes are included in lines 3 through 5 so the program can use the components of the classes. Notice that the implementations of the three classes are not in view here and do not need to be in view. This allows the code to be used without access to the source code for the actual implementation of the class. However, it should be clear that the header file definition must be available.
22 In this example program, only one object of each class is declared and used but as many as desired could be declared and used in order to accomplish the programming task at hand. The classes were developed, debugged, and stored away previously, and the interfaces were kept very simple. Example program > ALLVEHIC.CPP
23 Compile and Link The three classes and the main() program can be compiled in any order desired. All four must be compiled prior to linking the four resulting object (or binary) files together. Be sure you do the required steps to compile and execute this program because the effective use of C++ will require you to compile many separate files and link them together.
24 WHY THE #ifndef VEHICLE_H ? When we define the derived class car, we are required to supply it with the full definition of the interface to the vehicle class since car is a derived class of vehicle and must know all about its parent. We do that by including the vehicle class into the car class, and the car class can be compiled. The vehicle class must also be included in the header file of the truck class for the same reason.
25 When the preprocessor gets to the car class, it includes the vehicle class because it is listed in the car class header file, but since the vehicle class was already included in line 3 of ALLVEHIC.CPP, it is included twice and we attempt to re-declare the class vehicle. Of course it is the same declaration, but the system doesn't care, it simply doesn't allow re- declaration of a class. WHY THE #ifndef VEHICLE_H ?
26 Linked Lists Examples
27 The Main Concept Static Array Pre-allocation Required Waste-full if you allocate too much Fatal if you allocate too little Data has to be shifted when an item is inserted or deleted at specified position Dynamic Array Determine the size before allocating memory Costly reallocation, insertion, deletion Data has to be shifted Linked List Truly dynamic, memory is allocated as needed
28 Linked Lists To maintain a given order you don't have to store data in this order. Each item of the list points to the next one. You can always determine the successor, no matter where it is physically. You can insert and delete items without shifting the whole list. The size of the list can be increased easily by adding successors.
29 (a) A linked list of integers; (b) insertion; (c) deletion
30 Pointers A pointer variable (or just pointer) contains the location of address in memory, of a memory cell. By using a pointer to a particular memory cell, you can locate the cell and determine its content. int *p,q; q=1234; p=q;
31 Pointers: dynamic memory allocation A pointer can point at the memory area allocated at execution time. int *p; p=new int[10]; *(p+2)=1234; p[1]=2222; delete [] p; int *p; p=new int; *p=1234; delete p;
32 A pointer to an integer
33 (a) Declaring pointer variables; (b) pointing to statically allocated memory; (c) assigning a value
34 (d) Allocating memory dynamically; (e) assigning a value; (f) copying a pointer
35 (g) Allocating memory dynamically and assigning a value; (h) assigning NULL to a pointer variable; (i) de-allocating memory
36 An incorrect pointer to a de-allocated node
37 Programming with pointer variables and dynamically allocated memory
38 Programming with pointer variables and dynamically allocated memory
39 Programming with pointer variables and dynamically allocated memory
40 Pointer-based Linked Lists A linked list contains components that are linked to one another. Each component (a node) contains: a data item, a pointer to the next item.
41 A node
42 A Node Any time you allocate memory using new, you must de-allocate it by using delete. head points at the first element on the list. struct Node { int item; Node *next; }; Node *p,*head; head=NULL; p=new Node; p->item=1; p->next=NULL; head=p;... delete p;
43 A head pointer to a list
44 A misconception Memory is allocated for Node structure, head points at the allocated area. head points at 'nothing' The allocated memory is lost (a memory leak) You shouldn't allocate memory for head, it is just a pointer. head=new Node; head=NULL;
45 A lost cell
46 The List Traversal Let a current pointer point to the first node in the linked list. while (the current pointer is not NULL) {Display the data portion of the current node Set the current pointer to the next pointer of the current node } Node *cur;... for (cur=head; cur!=NULL; cur=cur->next) cout item << endl;
47 The effect of the assignment cur = cur->next
48 Deleting a Specified Node prev->next=cur->next; cur->next=NULL; delete cur; cur=NULL; Assumption: The linked list exists. There are three pointers set: head – the first element of the list, cur – the current element of the list, prev – the previous element of the list. Deletion:
49 Deleting a node from a linked list
50 Deleting the First Node The previous method doesn't work for the first element, because prev has nothing to point at. This is a special case. When the first node is deleted, the value of head has to be changed: head=head->next; The memory occupied by the first element has to be de-allocated.
51 Deleting the first node
52 Summary of the deletion process Locate the node using the List Traversal algorithm (keep in mind the special treatment of the first node). Disconnect the node from the list by changing the pointers. Return the node to the system (de- allocate memory).
53 Inserting a new node cur – points at the current node, prev – points at the previous node, newPtr – points at the new node which will be inserted before the current node. 1 st special case: insertion at the beginning. 2 nd special case: insertion at the end (actually not so special). newPtr=new Node; newPtr->data=999; newPtr->next=cur; prev->next=newPtr;
54 Inserting a new node into a linked list
55 Inserting at the beginning of the List head has to point to the new node. the new node has to point at the beginning of the linked list. newPtr->next=head; head=newPtr;
56 Inserting at the beginning of a linked list
57 Inserting at the end of the List It is not a special case. It works exactly as for other nodes (except the head) Add the new node when cur is NULL.
58 Inserting at the end of a linked list
59 Summary of the Insertion process Determine the point of insertion (using the List Traversal algorithm) Create a new node and store the new data in it. Connect the new node to the linked list by changing appropriate pointers.
60 Determining cur and prev The list should be traversed until the appropriate place for a new node is found. Let's create a linked list of sorted numbers. Insertions at the beginning and at the end are covered. prev=NULL; cur=head; while(cur != NULL and newValue > cur->item) {prev=cur; cur=cur->next; }
61 When prev points to the last node and cur is NULL, insertion will be at the end of the linked list
62 When prev is NULL and cur points to the first node, insertion or deletion will be at the beginning of the linked list
63 A pointer-Based ADT List typedef desired-type-of-list-item ListItemType; class List { public: // constructors and destructor: List(); // copy constructor List(const List& aList); ~List(); // list operations: bool isEmpty() const; int getLength() const; void insert(int index, ListItemType newItem); void remove(int index); void retrieve(int index, ListItemType& dataItem) const; private: struct ListNode // a node { ListItemType item; ListNode *next; }; int size; //number of items ListNode *head; ListNode *find(int index) const; // Returns a pointer to // the index-th node // in the linked list. };
64 Array vs. Pointer an Array-Based List Static arrays: fixed size, some space is wasted. Dynamic arrays: the initial size is approximated, some space can be wasted, reallocation is costly. To delete or insert an item all other items has to be shifted (costly) a Pointer-Based List memory allocation on demand, no direct access to a specified item (in order to find it the list has to be searched from its head).
65 Recursive Traversal Write the contents of a list of characters. struct Node { char item; Node *next; }; Node *stringPtr; void writeString(Node *stringPtr) { if (stringPtr != NULL) { // write the first character cout item; // write the string minus its first character writeString(stringPtr->next); } // end if } // end writeString
66 Recursive Insertion void linkedListInsert(Node* &headPtr, ItemType newItem) { if ((headPtr == NULL) || (newItem item)) { // base case: insert newItem at beginning // of the linked list to which headPtr points Node *newPtr = new Node; if (newPtr == NULL) throw ListException( "ListException: insert cannot allocate memory"); else { newPtr->item = newItem; newPtr->next = headPtr; headPtr = newPtr; } // end if } else linkedListInsert(headPtr->next, newItem); } // end linkedListInsert
67 A Pointer Implementation It is very common to implement a linked list using pointers and either structures or objects for the nodes. Examine the file l-simple.zip for a simple implementation using pointers.
68 Linked List Example -- l-list.zip This is an example of a singly linked linear list. It is in three files, list_node.h, main.cpp, and list_node.cpp. This illustrates the general idea of linked lists done in the classical, procedural style, characterized by struct for a node. Any node can be treated as the beginning of linked list.
69 Linked List Example -- l-class.zip Implementation of a simple linked list using classes.
70 End of Lecture All Programming Assignments due by the Final Exam day. (12/9) Final Exam preparation Thurs., 12/2