Presentation is loading. Please wait.

Presentation is loading. Please wait.

C++ Programming: Program Design Including Data Structures, Second Edition Chapter 13: Pointers, Classes, Lists, and Virtual Functions.

Similar presentations


Presentation on theme: "C++ Programming: Program Design Including Data Structures, Second Edition Chapter 13: Pointers, Classes, Lists, and Virtual Functions."— Presentation transcript:

1 C++ Programming: Program Design Including Data Structures, Second Edition Chapter 13: Pointers, Classes, Lists, and Virtual Functions

2 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 2 Objectives In this chapter you will: Learn about the pointer data type and pointer variables Explore how to declare and manipulate pointer variables Learn about the address of operator and the dereferencing operator Discover dynamic variables

3 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 3 Objectives Explore how to use the new and delete operators to manipulate dynamic variables Learn about pointer arithmetic Discover dynamic arrays Become aware of the shallow and deep copies of data Discover the peculiarities of classes with pointer data members

4 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 4 Objectives Explore how dynamic arrays are used to process lists Learn about virtual functions Examine the relationship between the address of operator and classes

5 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 5 Pointer Variables Pointer variable: the content is a memory address Declaring Pointer Variables: dataType *identifier ; int *p; char *ch;

6 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 6 Pointer Variables (continued) These statements are equivalent int *p; The character * can appear anywhere between type name and variable name int* p, q; Only p is the pointer variable, not q Here q is an int variable

7 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 7 Pointer Variables (continued) To avoid confusion, attach the character * to the variable name int *p, q; The following statement declares both p and q to be pointer variables of the type int int *p, *q;

8 expanded by J. Goetz, 2004 8 Recall that... char str [ 8 ]; str is the base address of the array. We say str is a pointer because its value is an address. It is a pointer constant because the value of str itself cannot be changed by assignment. It “points” to the memory location of a char. str [0] [1] [2] [3] [4] [5] [6] [7] ‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘\0’ 6000

9 expanded by J. Goetz, 2004 9 Addresses in Memory when a variable is declared, enough memory to hold a value of that type is allocated for it at an unused memory location. This is the address of the variable int x; float number; char ch; 2000 2002 2006 x number ch

10 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 10 Address Of Operator (&) The ampersand, &, is called the address of operator Address of operator: unary operator that returns the address of its operand int x; int *p; p = &x; // returns the address of x, store the address of x in p // x and value of p refer to the same memory location

11 expanded by J. Goetz, 2004 11 Obtaining Memory Addresses the address of a non-array variable can be obtained by using the address-of operator & int x; float number; char ch; cout << “Address of x is “ << &x << endl; cout << “Address of number is “ << &number << endl; cout << “Address of ch is “ << &ch << endl;

12 expanded by J. Goetz, 2004 12 What is a pointer variable? A pointer variable is a variable whose value is the address of a location in memory. to declare a pointer variable, you must specify the type of value that the pointer will point to, for example, int* ptr; // ptr will hold the address of an int char* q; // q will hold the address of a char enum ColorType {RED, GREEN, BLUE}; ColorType color; ColorType* colorPtr;

13 expanded by J. Goetz, 2004 13 Using a Pointer Variable int x; x = 12; int* ptr; ptr = &x; NOTE: Because ptr holds the address of x, we say that ptr “points to” x enum ColorType {RED, GREEN, BLUE}; ColorType color; ColorType* colorPtr = &color ; 2000 12 x 3000 2000 ptr

14 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 14 Dereferencing Operator (*) C++ uses * as  the binary multiplication operator and  as a unary operator When used as a unary operator, * Called the dereferencing operator or indirection operator Refers to the object to which its operand (that is, a pointer) points

15 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 15 Dereferencing Operator (*) int x = 25; int *p; p = &x; // store the address of x in p count << *p << endl; // prints 25 *p r efers to the object to which a pointer p points

16 expanded by J. Goetz, 2004 16 2000 *ptr 12 x 3000 2000 ptr int x; x = 12; int* ptr; ptr = &x; cout << *ptr; NOTE: The value pointed to by ptr is denoted by *ptr Unary operator * is the indirection (dereference) operator

17 expanded by J. Goetz, 2004 17 int x; x = 12; int* ptr; ptr = &x; *ptr = 5; // changes the value // at address ptr to 5 Using the Dereference Operator 2000 12 5 x 3000 2000 ptr

18 expanded by J. Goetz, 2004 18 char ch; ch = ‘A’; char* q; q = &ch; *q = ‘Z’; char* p; p = q; // the &ch has value 4000 // now p and q both point to ch Another Example 4000 *q A Z ch 5000 6000 4000 4000 q p

19 expanded by J. Goetz, 2004 19 ptr Using a Pointer to Access the Elements of a String ‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘\0’ 3000 char msg[ ] = “Hello”; ‘M’ ‘a’ 3001 char* ptr; 3000 ptr = msg; // recall that msg == &msg[ 0 ] *ptr = ‘M’ ; ptr++;// increments the address in ptr *ptr = ‘a’;

20 expanded by J. Goetz, 2004 20 int StringLength ( /* in */ const char str[ ] ) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Precondition: str is a null-terminated string // Postcondition: FCTVAL == length of str (not counting ‘\0’) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - { char* p ; int count = 0; p = str; while ( *p != ‘\0’ ) { count++ ; p++ ; // increments the address p by sizeof char } return count; } 20

21 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 21 C++ Data Types structured array struct union class address pointer reference simple integral enum char short int long bool floating float double long double

22 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 22 Classes, structs, and Pointer Variables Pointers can be declared to classes and structs To simplify the accessing of class or struct components via a pointer, C++ provides the member access operator arrow, -> The syntax for accessing a class (struct) member using the operator -> is: pointerVariableName->classMemberName

23 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 23 Using a Pointer to Access the Elements Syntax: PointerVariable -> MemberName or (* PointerVariable).MemberName TimeType startTime(8, 30, 0); TimeType* timePtr; (*timePtr).Increment(); // or timePtr ->Increment(); TimeType* myArray[20] (*myArray[4] ).Increment(); // or myArray[4]->Increment();

24 expanded by J. Goetz, 2004 Some C++ Pointer Operations Precedence Higher -> Select member of class pointed to Unary: ++ -- ! * new delete Increment, Decrement, NOT, Dereference, Allocate, Deallocate + - Add Subtract >= Relational operators == != Tests for equality, inequality Lower = Assignment 24

25 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 25 Initializing Pointer Variables C++ does not automatically initialize variables Pointer variables can be initialized using the constant value 0, called the “null pointer” denoted by NULL in header file cstddef p.1474. The following two statements are equivalent: p = NULL; // predefined constant p = 0;

26 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 26 Initializing Pointer Variables NOTE: It is an error to dereference a pointer whose value is NULL. Such an error may cause your program to crash, or behave erratically. It is the programmer’s job to check for this. while (ptr != NULL) {... // ok to use *ptr here }

27 expanded by J. Goetz, 2004 27 3 Kinds of Program Data STATIC DATA: memory allocation exists throughout execution of program static long currentSeed; AUTOMATIC DATA: automatically created at function entry, resides in activation frame of the function, and is destroyed when returning from function DYNAMIC DATA: explicitly allocated and deallocated during program execution by C++ instructions written by programmer using operators new and delete

28 expanded by J. Goetz, 2004 28 Allocation of Memory STATIC ALLOCATION Static allocation is the allocation of memory space at compile time. DYNAMIC ALLOCATION Dynamic allocation is the allocation of memory space at run time by using operator new.

29 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 29 Dynamic Variables Dynamic variables: created during execution  using pointers Two operators, new and delete,  to create and destroy dynamic variables new and delete are reserved words

30 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 30 Operator new The syntax for new: new dataType; //to allocate a single variable e.g. p = new int; new dataType [intExp]; //to allocate an array of variables e.g. p = new char[5]; where intExp is any expression evaluating to a positive integer If memory is available, in an area called the heap (or free store) new allocates memory of the designated type and returns a pointer to it. Otherwise, program terminates with error message. Allocated memory is uninitialized The dynamically allocated object exists until the delete operator destroys it.

31 expanded by J. Goetz, 2004 31 2000 ptr Dynamically Allocated Data char* ptr; ptr = new char; *ptr = ‘B’; cout << *ptr;

32 expanded by J. Goetz, 2004 32 Dynamically Allocated Data p.710 char* ptr; ptr = new char; *ptr = ‘B’; cout << *ptr; NOTE: The statement stores the address of the allocated memory in ptr 2000 ptr

33 expanded by J. Goetz, 2004 33 Dynamically Allocated Data char* ptr; ptr = new char; *ptr = ‘B’; cout << *ptr; NOTE: Dynamic data has no variable name 2000 ptr ‘B’

34 expanded by J. Goetz, 2004 34 Dynamically Allocated Data char* ptr; ptr = new char; *ptr = ‘B’; cout << *ptr; delete ptr; 2000 ptr NOTE: the delete operator 1.deallocates the memory pointed to by ptr and 2. pointed- to variable *ptr is deleted (dynamic data is deleted) ?

35 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 35 Operator delete delete destroys dynamic variables The syntax of delete has two forms (statements): delete pointer; //to destroy a single dynamic variable delete [] pointer; //to destroy a dynamically //created array Operator delete returns to the free store memory which was previously allocated at run-time by operator new it deletes the pointed-to variable (dereferenced variable) The object or array currently pointed to by the pointer is deallocated, and the pointer is considered unassigned (undefined).

36 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 36 Operator delete The syntax of delete has two forms (statements): delete pointer; //to destroy a single dynamic variable delete [] pointer; //to destroy a dynamically //created array The statements delete p; delete [] name; deallocate memory referenced by the pointers p and name Square brackets are used with delete to deallocate a dynamically allocated array.

37 expanded by J. Goetz, 2004 37 int* ptr = new int; *ptr = 3; ptr = new int; // changes value of ptr *ptr = 4; // here the 3 becomes inaccessible What happens here? 3 ptr 3 ptr 4

38 expanded by J. Goetz, 2004 38 Inaccessible Object An inaccessible object is an unnamed object that was created by operator new and which a programmer has left without a pointer to it. int* ptr = new int; *ptr = 8; int* ptr2 = new int; *ptr2 = -5; How else can an object become inaccessible? 8 ptr -5 ptr2

39 expanded by J. Goetz, 2004 39 Making an Object Inaccessible int* ptr = new int; *ptr = 8; int* ptr2 = new int; *ptr2 = -5; ptr = ptr2; // here the 8 becomes inaccessible 8 ptr -5 ptr2 8 ptr -5 ptr2

40 expanded by J. Goetz, 2004 40 Memory Leak A memory leak is the loss of available memory space that occurs when dynamic data is allocated but never deallocated.

41 expanded by J. Goetz, 2004 41 is a pointer that points to dynamic memory that has been deallocated int* ptr = new int; *ptr = 8; int* ptr2 = new int; *ptr2 = -5; ptr = ptr2; A Dangling Pointer 8 ptr -5 ptr2 FOR EXAMPLE,

42 expanded by J. Goetz, 2004 42 int* ptr = new int; *ptr = 8; int* ptr2 = new int; *ptr2 = -5; ptr = ptr2; // here the 8 becomes inaccessible delete ptr2; // ptr is left dangling !!! ptr2 = NULL; Leaving a Dangling Pointer 8 ptr -5 ptr2 8 ptr NULL ptr2

43 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 43 Operations on Pointer Variables 1.Assignment: value of one pointer variable can be assigned to another pointer of same type 2.Relational operations: two pointer variables of same type can be compared for equality, etc. 3.Some limited arithmetic operations: Integer values can be added and subtracted from a pointer variable Value of one pointer variable can be subtracted from another pointer variable

44 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 44 Some C++ Pointer Operations int arr[10]; int* ptr; the assignment statement ptr = arr; has the effect as ptr = &arr[0];

45 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 45 Some C++ Pointer Operations The logical NOT operator can be used to test the null pointer: if (!ptr) //in spite of ptr is a pointer expression, not a Boolean expression DoSomething(); The same but preferable: if (ptr == NULL) DoSomething();

46 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 46 Some C++ Pointer Operations To test pointers: int *intPtr1, *intPtr2; if (intPtr1 == intPtr2) To test the integers that intPtr1, intPtr2 point to: if (*intPtr1 == *intPtr2)

47 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 47 Operations on Pointer Variables When an integer is added to a pointer variable Value of pointer is incremented by integer times the size of the memory that the pointer points to If ptr points some element of an array (int array[]), then ptr + 7 points the array element that is seventh beyond the one currently pointed to by ptr (regardless of the size in bytes of each array element) When an integer is subtracted from a pointer variable Value of pointer variable is decremented by the integer times the size of the memory to which the pointer is pointing

48 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 48 Dynamic Arrays Dynamic array: array created during execution Use the second form of the new operator to create a dynamic array The statement p = new int[10]; allocates 10 contiguous memory locations, each of the type int, and stores the address of the first memory location into p

49 expanded by J. Goetz, 2004 49 Dynamic Array Allocation char *ptr; // ptr is a pointer variable that // can hold the address of a char ptr = new char[ 5 ]; // dynamically, during run time, allocates // memory for a 5 character array // and stores the base address into ptr ptr 6000

50 expanded by J. Goetz, 2004 50 Dynamic Array Allocation char *ptr ; ptr = new char[ 5 ]; strcpy( ptr, “Bye” ); ptr[ 1 ] = ‘u’; // a pointer can be subscripted or ptr++; *ptr = ‘u’; cout << ptr[ 2] ; ptr 6000 ‘B’ ‘y’ ‘e’ ‘\0’ ‘u’

51 expanded by J. Goetz, 2004 51 Recall that... char list [ 8 ]; str is the base address of the array. We say list is a pointer because its value is an address. It is a pointer constant because the value of list itself cannot be changed by assignment – list++. It “points” to the memory location of a list. list [0] [1] [2] [3] [4] [5] [6] [7] ‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘\0’ 6000

52 expanded by J. Goetz, 2004 52 Dynamic Array Deallocation char *ptr ; ptr = new char[ 5 ]; strcpy( ptr, “Bye” ); ptr[ 1 ] = ‘u’; delete ptr; // deallocates array pointed to by ptr // ptr itself is not deallocated // the value of ptr is undefined. ptr ?

53 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 53 Dynamic Array Allocation created by user int *intList; int arraySize; cout << “Enter the array size”; cin >> arraySize; cout << endl; intList = new int [arraySize];

54 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 54 Functions and Pointers A pointer variable can be passed as a parameter either by value or by reference To make a pointer a reference parameter in a function heading, * appears before the & between the data type name and the identifier void example(int* &p, double *q) { ….} // Both p and q are pointers A function can return a value of type pointer int* example (int* &p, double *q)

55 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 55 Shallow vs Deep Copy and Pointers In a shallow copy, two or more pointers of the same type point to the same memory (the same data) int *first; int *second; first = new int[10]; // suppose that it is filled out second = first; // shallow copy, to same data

56 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 56 Shallow vs Deep Copy and Pointers In a deep copy, two or more pointers have their own data int *first; int *second; first = new int[10]; // suppose that it is filled out second = new int[10]; for (int j = 0; j < 10; j++) second [j] = first [j]; // it produces a deep copy,

57 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 57 Classes and Pointers: Some Peculiarities We’ll use: pointerDataClass objectOne; pointerDataClass objectTwo;

58 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 58 Destructor Suppose that during program execution the pointer p creates a dynamic array When objectOne goes out of scope, all the data members of objectOne are destroyed If pointer p does not use the delete operator to deallocate a dynamic array Memory of the dynamic array stays marked as allocated, even though it is inaccessible

59 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 59 Destructor (continued) Destructor automatically executes whenever a class object goes out of scope Put code in the destructor to ensure that when objectOne goes out of scope, the memory created by pointer p is deallocated pointerDataClass:: ~pointerDataClass() { delete [ ] p; }

60 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 60 Assignment Operator objectTwo = objectOne; // shallow copy To avoid shallow copying of data for classes with a pointer data member, overload the assignment operator =>ch.14

61 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 61 objectTwo = objectOne; // shallow copy

62 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 62 Once overloaded, both the objects objectOne and objectTwo have their own data

63 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 63 Copy Constructor Consider the following statement: pointerDataClass objectThree(objectOne); objectThree is being declared and initialized using the value of objectOne Called default member-wise initialization Initialization due to constructor, called copy constructor provided by the compiler This default initialization would lead to a shallow copying of the data

64 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 64 Copy Constructor (continued) If a class has pointer data members: During object declaration, initialization of one object using the value of another object leads to shallow copying of data If an object is passed by value and the default member-wise copying of data is allowed, it would lead to shallow copying of data In both cases, must override the definition of the copy constructor provided by the compiler

65 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 65 Copy Constructor (continued) Add a statement that includes the copy constructor in the definition of the class, and then write its definition For the class pointerDataClass, you can overcome shallow copying of data by including the copy constructor when there is a copy constructor provided for a class, the copy constructor is used to make copies for pass by value

66 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 66 Copy Constructor (continued) The general syntax to include the copy constructor in the definition of a class is: className(const className& otherObject);

67 expanded by J. Goetz, 2004 67 // SPECIFICATION FILE (dynarray.h) // Safe integer array class allows 1.run-time //specification of size, 2. prevents indexes from going //out of bounds, 3. allows aggregate array copying and //initialization. class DynArray { public: DynArray( /* in */ int arrSize ); // Constructor. // PRE: arrSize is assigned // POST: IF arrSize >= 1 && enough memory THEN // Array of size arrSize is created with // all elements == 0 ELSE error message. DynArray( const DynArray& otherArr ); // Copy constructor. // POST: this DynArray is a deep copy of otherArr // Is implicitly called for initialization.

68 expanded by J. Goetz, 2004 68 // SPECIFICATION FILE continued (dynarray.h) ~DynArray( ); // Destructor. // POST: Memory for dynamic array deallocated. int ValueAt ( /* in */ int i ) const; // PRE: i is assigned. // POST: IF 0 <= i < size of this array THEN // FCTVAL == value of array element at index i // ELSE error message. void Store ( /* in */ int val, /* in */ int i ) // PRE: val and i are assigned // POST: IF 0 <= i < size of this array THEN // val is stored in array element i // ELSE error message. 68

69 expanded by J. Goetz, 2004 69 // SPECIFICATION FILE continued (dynarray.h) void CopyFrom ( /* in */ DynArray otherArr); // POST: IF enough memory THEN // new array created (as deep copy) // with size and contents // same as otherArr // ELSE error message. private: int* arr ; int size ; }; 69

70 expanded by J. Goetz, 2004 70 class DynArray 80 40 90 0 0 Private data: size 5 arr 6000 Free store 6000 DynArray Store ValueAt DynArray ~DynArray CopyFrom

71 expanded by J. Goetz, 2004 71 DynArray::DynArray( /* in */ int arrSize ) // Constructor. // PRE: arrSize is assigned // POST: IF arrSize >= 1 && enough memory THEN // Array of size arrSize is created with // all elements == 0 ELSE error message. { int i; if ( arrSize < 1 ) { cerr << “DynArray constructor - invalid size: “ << arrSize << endl; exit(1); } arr = new int[arrSize] ; // allocate memory pointed by arr size = arrSize; for (i = 0; i < size; i++) arr[i] = 0; } 71

72 expanded by J. Goetz, 2004 72 DynArray beta(5); //constructor 0 0 0 Private data: size 5 arr 2000 Free store 2000 DynArray Store ValueAt DynArray ~DynArray CopyFrom beta

73 expanded by J. Goetz, 2004 73 beta.Store(75, 2); 0 75 0 0 Private data: size 5 arr 2000 Free store 2000 DynArray Store ValueAt DynArray ~DynArray CopyFrom beta

74 expanded by J. Goetz, 2004 74 void DynArray::Store ( /* in */ int val, /* in */ int i ) // PRE: val and i are assigned // POST: IF 0 <= i < size of this array THEN // arr[i] == val // ELSE error message. { if ( i = size ) { cerr << “Store - invalid index : “ << i << endl; exit(1) ; } arr[i] = val ; } 74

75 expanded by J. Goetz, 2004 75 0 0 Private: size 4 arr 3000 3000 Private: size 5 arr 2000 2000 0 75 0 0 gamma beta DynArray gamma(4);//constructor DynArray Store ValueAt DynArray ~DynArray CopyFrom DynArray Store ValueAt DynArray ~DynArray CopyFrom

76 expanded by J. Goetz, 2004 76 0 -8 0 Private: size 4 arr 3000 3000 Private: size 5 arr 2000 2000 0 75 0 0 gamma beta gamma.Store(-8,2); DynArray Store ValueAt DynArray ~DynArray CopyFrom DynArray Store ValueAt DynArray ~DynArray CopyFrom

77 expanded by J. Goetz, 2004 77 int DynArray::ValueAt ( /* in */ int i ) const // PRE: i is assigned. // POST: IF 0 <= i < size THEN // FCTVAL == arr[i] // ELSE halt with error message. { if ( i = size ) { cerr << “ValueAt - invalid index : “ << i << endl; exit(1) ; } return arr[i]; } 77

78 expanded by J. Goetz, 2004 78 Why is a destructor needed? When a DynArray class variable goes out of scope, the memory space for data members size and pointer arr is deallocated. But the dynamic array that arr points to is not automatically deallocated. A class destructor is used to deallocate the dynamic memory pointed to by the data member.

79 expanded by J. Goetz, 2004 79 DynArray::~DynArray( ); // Destructor. // POST: Memory for dynamic array deallocated. { delete [ ] arr ; } 79 class DynArray Destructor

80 expanded by J. Goetz, 2004 80 What happens... When a function is called that uses pass by value for a class object of DynArray type? 0 75 0 0 Private: size 5 arr 2000 2000 DynArray Store ValueAt DynArray ~DynArray CopyFrom beta

81 expanded by J. Goetz, 2004 81 int main() { DynArray beta(5); … SomeFunc(beta); … } void SomeFunc( DynArray someArr ) // uses pass by value, someArr is a shallow copy, // their arr pointers point to the same dynamic array, so //this function can corrupt the dynamic //array used by class object beta { … } 81 Passing a Class Object by Value

82 expanded by J. Goetz, 2004 82 By default, Pass-by-value makes a shallow copy DynArray beta(5); // CLIENT CODE. SomeFunc( beta ); // function call beta someArr 0 75 0 0 2000 DynArray. Private: size 5 arr 2000 DynArray. Private: size 5 arr 2000 shallow copy

83 expanded by J. Goetz, 2004 83 Shallow Copy vs. Deep Copy a shallow copy copies only the class data members, and does not make a copy of any pointed-to data a deep copy copies not only the class data members, but also makes a separate stored copy of any pointed-to data

84 expanded by J. Goetz, 2004 84 What’s the difference? a shallow copy shares the pointed to dynamic data with the original class object a deep copy makes its own copy of the pointed to dynamic data at different locations than the original class object

85 expanded by J. Goetz, 2004 85 0 75 0 0 4000 DynArray. Private: size 5 arr 4000 beta someArr deep copy 0 75 0 0 2000 DynArray. Private: size 5 arr 2000 Making a (Separate) Deep Copy

86 expanded by J. Goetz, 2004 86 Initialization of Class Objects C++ defines initialization to mean the following 1. initialization in a variable declaration DynArray beta = someArr; // member by member copy 1. passing an object argument by value 2. returning an object as the return value of a function return someObject; by default, C++ uses shallow copies for these initializations

87 expanded by J. Goetz, 2004 87 Initialization of Class Objects when a class has a data member pointer to dynamically allocated data, you should write what is called a copy constructor the copy constructor is implicitly called in initialization situations and makes a deep copy of the dynamic data in a different memory location

88 expanded by J. Goetz, 2004 88 More about Copy Constructors when there is a copy constructor provided for a class, the copy constructor is used to make copies for pass by value you do not call the copy constructor like other constructors, it has no return type because the copy constructor properly defines pass by value for your class, it must use pass by reference in its definition with const

89 expanded by J. Goetz, 2004 89 Copy Constructor copy constructor is a special member function of a class that is implicitly automatically called in these 3 situations: 1.initializing an object variable in its declaration 2.passing object parameters by value 3.returning an object as the return value of a function

90 expanded by J. Goetz, 2004 90 0 75 0 0 Private: size 5 arr 2000 2000 Private: size 5 arr 4000 4000 0 75 0 0 beta someArr SomeFunc(beta); // copy-constructor // beta passed by value DEEP COPY DynArray Store ValueAt DynArray ~DynArray CopyFrom DynArray Store ValueAt DynArray ~DynArray CopyFrom

91 expanded by J. Goetz, 2004 91 // FUNCTION CODE void SomeFunc( DynArray someArr ) // Uses pass by value { someArr.Store(290, 2);. } WHAT HAPPENS IN THE SHALLOW COPY SCENARIO? 91 Suppose SomeFunc calls Store

92 expanded by J. Goetz, 2004 92 DynArray beta(5); // CLIENT CODE. SomeFunc( beta); beta.arr[2] has changed beta someArr 0 290 0 0 2000 DynArray. Private: size 5 arr 2000 DynArray. Private: size 5 arr 2000 shallow copy

93 expanded by J. Goetz, 2004 93 beta.arr[2] has changed NOTICE THAT NOT JUST FOR THE SHALLOW COPY, BUT ALSO FOR ARGUMENT beta, THE DYNAMIC DATA HAS CHANGED! beta someArr 0 290 0 0 2000 DynArray. Private: size 5 arr 2000 DynArray. Private: size 5 arr 2000 shallow copy

94 expanded by J. Goetz, 2004 94 CONSTRUCTOR COPY CONSTRUCTOR DESTRUCTOR Classes with Data Member Pointers Need

95 expanded by J. Goetz, 2004 95 DynArray::DynArray( const DynArray& otherArr ) // Copy constructor // Implicitly called for deep copy in initializations. // POST:If room on free store THEN // new array of size otherArr.size is created // on free store && arr == its base address // && size == otherArr.size // && arr[0..size-1] == otherArr.arr[0..size-1] // ELSE error message. { int i ; size = otherArr.size ; arr = new int[size] ; //!!! allocate memory for copy // arr hasn’t exist so far for ( i = 0; i< size ; i++ ) arr[i] = otherArr.arr[i] ; // copies array } // the copy constructor is creating a new class object that doesn’t // already exist. 95

96 expanded by J. Goetz, 2004 96 What about the assignment operator? the default method used for assignment of class objects makes a shallow copy if your class has a data member pointer to dynamic data, you should write a member function to create a deep copy of the dynamic data

97 expanded by J. Goetz, 2004 97 gamma.CopyFrom(beta); ? 75 ? ? Private: size 5 arr 3000 3000 Private: size 5 arr 2000 2000 ? 75 ? ? gamma beta DEEP COPY DynArray Store ValueAt DynArray ~DynArray CopyFrom DynArray Store ValueAt DynArray ~DynArray CopyFrom

98 expanded by J. Goetz, 2004 98 void DynArray::CopyFrom ( /* in */ DynArray otherArr ) // Creates a deep copy of otherArr. // POST: Array pointed to by arr@entry deallocated // && IF room on free store // THEN new array is created on free store // && arr == its base address // && size == otherArr.size // && arr[0..size-1] == otherArr[0..size-1] // ELSE halts with error message. { int i ; delete [ ] arr ;//!!! delete current array // next the same as a copy constructor size = otherArr.size ; arr = new int [size] ;//!!! allocate new array for ( i = 0; i< size ; i++ ) // deep copy array arr[i] = otherArr.arr[i] ; } 98

99 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 99 Array-Based Lists List: a homogeneous collection of elements List length: number of elements in the list Operations performed on a list are: Create the list and initialize to an empty state Determine whether the list is empty Determine whether the list is full Find the size of the list Destroy, or clear the list

100 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 100 Array-Based Lists (continued) Operations performed on a list are: Determine whether an item is the same as a given list element Insert an item in the list at the specified location Remove an item from the list at the specified location Replace an item at the specified location with another item Retrieve an item from the list at the specified location Search the list for a given item

101 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 101 Array-Based Lists (continued) Can create dynamic arrays, which permit user to specify the size of the array We need 3 variables to maintain and process array-based list: list: the array holding the list elements length: the length of the list (#items in list) maxSize: the maximum size of the array

102 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 102 #ifndef H_arrayListType // arrayListType.h #define H_arrayListType class arrayListType { public: bool isEmpty() const; //Function to determine whether the list is empty //Postcondition: Returns true if the list is empty; // otherwise, returns false. bool isFull() const; //Function to determine whether the list is full //Postcondition: Returns true if the list is full; // otherwise, returns false. int listSize() const; //Function to determine the number of elements in the list //Postcondition: Returns the value of length. int maxListSize() const; //Function to determine the maximum size of the list //Postcondition: Returns the value of maxSize. void print() const; //Function to output the elements of the list //Postcondition: Elements of the list are output on the // standard output device. bool isItemAtEqual(int location, int item) const; //Function to determine whether item is the same as //the item in the list at the position specified //by location //Postcondition: Returns true if the list[location] // is the same as item; otherwise, // returns false. void insertAt(int location, int insertItem); //Function to insert insertItem in the list at the //position specified by location. //Postcondition: Starting at location, the elements // of the list are shifted down, // list[location] = insertItem;, and // length++; // If the list is full or location is out of // range, an appropriate message is displayed. void insertEnd(int insertItem); //Function to insert an item at the end of the list //The parameter insertItem specifies the item to be //inserted. //Postcondition: list[length] = insertItem; and length++; // If the list is full, an appropriate // message is displayed. void removeAt(int location); //Function to remove the item from the list at the //position specified by location //Postcondition: The list element at list[location] is // removed and length is decremented by 1. // If location is out of range, an appropriate message // is displayed. void retrieveAt(int location, int& retItem); //Function to retrieve the element from the list at the //position specified by location //Postcondition: retItem = list[location] // If location is out of range, an appropriate // message is displayed. void replaceAt(int location, int repItem); //Function to replace the elements in the list at the //position specified by location. The item to be replaced //is specified by the parameter repItem. //Postcondition: list[location] = repItem // If location is out of range, an appropriate // message is displayed. void clearList(); //Function to remove all the elements from the list //After this operation, the size of the list is zero. //Postcondition: length = 0; int seqSearch(int item) const; //Function to search the list for a given item. //Postcondition: If the item is found, returns the location // in the array where the item is found; // otherwise, returns -1.

103 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 103 void insert(int insertItem); //Function to insert the item specified by the parameter //insertItem at the end of the list. However, first the //list is searched to see whether the item to be inserted //is already in the list. //Postcondition: list[length] = insertItem and length++ // If the item is already in the list or the list // is full, an appropriate message is displayed. void remove(int removeItem); //Function to remove an item from the list. The parameter //removeItem specifies the item to be removed. //Postcondition: If removeItem is found in the list, // it is removed from the list and length is // decremented by one. arrayListType(int size = 100); //constructor //Creates an array of the size specified by the //parameter size. The default array size is 100. //Postcondition: The list points to the array, length = 0, // and maxSize = size arrayListType (const arrayListType& otherList); //copy constructor ~arrayListType(); //destructor //Deallocate the memory occupied by the array. protected: // later use for the derived class int *list; //array to hold the list elements int length; //variable to store the length of the list int maxSize; //variable to store the maximum size of the list }; #endif

104 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 104 #include // arrayListTypeImp.cpp #include #include "arrayListType.h" using namespace std; bool arrayListType::isEmpty() const { return (length == 0); } bool arrayListType::isFull() const { return (length == maxSize); } int arrayListType::listSize() const { return length; } int arrayListType::maxListSize() const { return maxSize; } void arrayListType::print() const { int i; for (i = 0; i < length; i++) cout << list[i] << " "; cout << endl; } bool arrayListType::isItemAtEqual(int location, int item) const { return(list[location] == item); } void arrayListType::insertAt(int location, int insertItem) { int i; if (location = maxSize) cout << "The position of the item to be inserted " << "is out of range." << endl; else if (length >= maxSize) //list is full cout << "Cannot insert in a full list." << endl; else { for (i = length; i > location; i--) list[i] = list[i - 1]; //move the elements down list[location] = insertItem; //insert insertItem //at the specified //position length++;//increment the length } } //end insertAt void arrayListType::insertEnd(int insertItem) { if (length >= maxSize) //the list is full cout << "Cannot insert in a full list." << endl; else { list[length] = insertItem;//insert the item at the end length++;//increment length } } //end insertEnd

105 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 105 void arrayListType::removeAt(int location) { int i; if (location = length) cout << "The location of the item to be removed " << "is out of range." << endl; else { for (i = location; i < length - 1; i++) list[i] = list[i+1]; length--; } } //end removeAt void arrayListType::retrieveAt(int location, int& retItem) { if (location = length) cout << "The location of the item to be retrieved is " << "out of range." << endl; else retItem = list[location]; } // retrieveAt void arrayListType::replaceAt(int location, int repItem) { if (location = length) cout << "The location of the item to be replaced is " << "out of range." << endl; else list[location] = repItem; } //end replaceAt void arrayListType::clearList() { length = 0; } // end clearList arrayListType::arrayListType(int size) { if (size <= 0) { cout << "The array size must be positive. Creating " << "an array of size 100. " << endl; maxSize = 100; } else maxSize = size; length = 0; list = new int[maxSize]; assert(list != NULL); } arrayListType::~arrayListType() { delete [ ] list; } //copy constructor arrayListType::arrayListType(const arrayListType& otherList) { int j; maxSize = otherList.maxSize; length = otherList.length; list = new int[maxSize]; //create the array assert(list != NULL); //terminate if unable to allocate memory space for (j = 0; j < length; j++) //copy otherList list [j] = otherList.list[j]; }//end copy constructor

106 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 106 int arrayListType::seqSearch(int item) const { int loc; bool found = false; for (loc = 0; loc < length; loc++) if (list[loc] == item) { found = true; break; } if (found) return loc; else return -1; } //end seqSearch void arrayListType::insert(int insertItem) { int loc; if (length == 0) //list is empty list[length++] = insertItem; //insert the item and //increment the length else if (length == maxSize) cout << "Cannot insert in a full list." << endl; else { loc = seqSearch(insertItem); if (loc == -1) //the item to be inserted //does not exist in the list list[length++] = insertItem; else cout << "the item to be inserted is already " << "in the list. No duplicates are " << "allowed." << endl; } } //end insert void arrayListType::remove(int removeItem) { int loc; if (length == 0) cout << "Cannot delete from an empty list." << endl; else { loc = seqSearch(removeItem); if (loc != -1) removeAt(loc); else cout << "The tem to be deleted is not in the list." << endl; } } //end remove Insert: add a new item to the list Duplicates are not allowed Search list to determine if item to be inserted is already in the list If not in the list, insert at the end of the list and increment length by 1 Remove: delete an item from the list The item to be deleted is passed as a parameter to this function First call search to determine if item to be deleted is in the list If found remove from the list and decrement length by 1

107 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 107 #include // testProgArrayBasedList.cpp #include "arrayListType.h" using namespace std; void testCopyConstructor(arrayListType testList); int main() { arrayListType list;//Line 1 int num; //Line 2 cout << "Line 3: Enter numbers ending with -999" << endl;//Line 3 cin >> num;//Line 4 while(num != -999)//Line 5 { list.insert(num);//Line 6 cin >> num;//Line 7 } cout << "Line 8: The list you entered is: " << endl;//Line 8 list.print();//Line 9 cout << "Line 10: The list size is: " << list.listSize() << endl;//Line 10 cout << "Line 11: Enter the item to be deleted: ";//Line 11 cin >> num; //Line 12 cout << endl; //Line 13 list.remove(num); //Line 14 cout << "Line 15: After removing " << num << " the list is: " << endl; //Line 15 list.print(); //Line 16 cout << "Line 16: The list size is: " << list.listSize() << endl; //Line 17 //test copy constructor testCopyConstructor(list);//Line 18 cout << "Line 19: The list after the copy " << "constructor." << endl;//Line 19 list.print();//Line 20 cout << "Line 21: The list size is: " << list.listSize() << endl;//Line 21 return 0;//Line 22 } void testCopyConstructor(arrayListType testList) { cout << "Line 23: Inside the function " << "testCopyConstructor." << endl;//Line 23 testList.print();//Line 24 cout << "Line 25: The list size is: " << testList.listSize() << endl;//Line 25 }

108 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 108 Copy Constructor

109 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 109 Search The following function performs a sequential search on a list:

110 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 110 Inheritance, Pointers, And Virtual Functions C++ allows the user to pass an object of a derived class to a formal parameter of the base class type Compile-time binding: necessary code to call a specific function is generated by the compiler Also known as static binding

111 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 111 Inheritance, Pointers, And Virtual Functions (continued) With virtual functions, binding occurs during execution, not at compile time Called run-time binding Compiler does not generate code to call a specific function  Generates enough information for the run-time system to generate specific code for the appropriate function call Also known as dynamic binding

112 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 112 // derivedClass.h #ifndef H_derivedClassVirtual #define H_derivedClassVirtual #include "baseClass.h" class derivedClass: public baseClass { public: void print(); derivedClass(int u = 0, int v = 0); private: int a; }; #endif // derivedClass.cpp #include #include "derivedClass.h" using namespace std; void derivedClass::print() { cout<<"In derivedClass ***: "; baseClass::print(); cout<<"In derivedClass a = "<<a<<endl; } derivedClass::derivedClass(int u, int v) : baseClass(u) { a = v; } // mainProgram.cpp #include #include "derivedClass.h" using namespace std; void callPrint(baseClass& p); int main() { baseClass one(5);//Line 1 derivedClass two(3, 15);//Line 2 one.print();//Line 3 two.print();//Line 4 cout<<"*** Calling the function callPrint ***" <<endl;//Line 5 callPrint(one); //Line 6 callPrint(two); //Line 7 // run-time binding // b/c of print() declaration in the base class is virtual return 0; } // baseClassImpl.cpp #include #include "baseClass.h" using namespace std; void baseClass::print() { cout<<"In baseClass x = "<<x<<endl; } baseClass::baseClass(int u) { x = u; } // baseClass.h #ifndef H_baseClassVirtual #define H_baseClassVirtual class baseClass { public: virtual void print(); //virtual function baseClass( int u = 0); private: int x; }; #endif void callPrint( baseClass& p ) { p.print(); } declaring a member function to be virtual instructs the compiler to generate code that guarantees dynamic binding

113 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 113 // // mainProgram.cpp - equivalent code of the previous mainProgram.cpp: #include #include "derivedClass.h" using namespace std; void callPrint(baseClass *p); int main() { baseClass *q; //Line 1 derivedClass *r; //Line 2 q = new baseClass(5); //Line 3 r = new derivedClass(3,15);//Line 4 q->print();//Line 5 r->print();//LIne 6 cout << "*** Calling the function callPrint ***" << endl;//Line 7 callPrint(q);//Line 8 callPrint(r);//Line 9 // pointer of the derived class is passed as an actual parameter return 0; } void callPrint(baseClass *p) // a formal parameter is a pointer to a class { // pointer of the derived class is passed as an actual parameter p->print(); // p uses a virtual function of the base class so // we can effectively pass a derived class object as an actual parameter to p } // if p passes as a value parameter callPrint(baseClass p); // it will copy to p only the data member x and p->print() and will be executed from the base class // mainProgram.cpp #include #include "derivedClass.h" using namespace std; void callPrint(baseClass& p); int main() { baseClass one(5);//Line 1 derivedClass two(3, 15);//Line 2 one.print();//Line 3 two.print();//Line 4 cout<<"*** Calling the function callPrint ***" <<endl;//Line 5 callPrint(one); //Line 6 callPrint(two); //Line 7 // run-time binding // b/c of print() declaration in the base class as virtual return 0; }

114 expanded by J. Goetz, 2004 114 Using virtual functions in C++ dynamic binding requires pass-by-reference when passing a class object to a function in the declaration for a virtual function, the word virtual appears only in the base class if a base class declares a virtual function, it must implement that function, even if the body is empty a derived class is not required to re-implement a virtual function. If it does not, the base class version is used

115 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 115 Classes and Virtual Destructors Destructor is automatically executed when the class object goes out of scope Virtual destructor of a base class automatically makes destructor of a derived class virtual If a derived class object is passed to a formal parameter of the base class type, when the object goes out of scope, the destructor of the derived class executes and After executing the destructor of the derived class, the destructor of the base class executes

116 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 116 Reference Types int & intRef; declares that intRef is a variable that contain the address of an int variable General syntax: DataType & Variable, & Variable ….; Only the operation is defined is initialization: i.e. explicit initialization or passing an argument to a parameter or initialization by returning a function value. Reference and pointer variables contain addresses of data object

117 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 117 Reference and pointer variables differences the dereferencing and address of operators (* and & ) are not used with reference variables. After a reference variable has been declared, the compiler invisibly dereferences every single appearance of that reference variable. Only the operation is defined at initialization. the compiler treats a reference variable as if it were a constant pointer  it cannot be reassigned after being initialized

118 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 118 Address of Operator & Classes The address of operator can create aliases to an object Consider the following statements: int x; int &y = x; x and y refer to the same memory location y is like a constant pointer variable The statement y = 25; sets the value of y and hence of x to 25 Similarly, the statement x = 2 * x + 30; updates the value of x and hence of y

119 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 119 // Implementation file testAdd.cpp #include #include "testAdd.h“ using namespace std; void testAddress::setX(int inX) { x = inX; } void testAddress::printX() const { cout << x; } int& testAddress::addressOfX() { return x; } //header file testAdd.h #ifndef H_testAdd #define H_testAdd class testAddress { public: void setX(int); void printX() const; int& addressOfX(); //this function // returns the address //of the private data member private: int x; }; #endif //Test program. #include #include "testAdd.h“ using namespace std; int main() { testAddress a; int &y = a.addressOfX(); a.setX(50); cout << "x in class testAddress = "; a.printX(); // prints x = 50 cout << endl; y = 25; cout << "After y = 25, x in class testAddress = "; a.printX(); / / prints x = 25 cout << endl; return 0; }

120 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 120 Summary Pointer variables contain the addresses of other variables as their values Declare a pointer variable with an asterisk, *, between the data type and the variable & is called the address of operator & returns the address of its operand Unary operator * is the dereference operator

121 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 121 Summary The member access operator arrow, ->, accesses the component of an object pointed to by a pointer Dynamic variable: created during execution Operator new creates a dynamic variable Operator delete deallocates memory occupied by a dynamic variable Dynamic array: created during execution

122 C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004 122 Summary Shallow copy: two or more pointers of the same type point to the same memory Deep copy: two or more pointers of the same type have their own copies of the data List: homogeneous collection of elements C++ allows the user to pass an object of a derived class to a formal parameter of the base class type The binding of virtual functions occurs at execution time, not at compile time, and is called dynamic or run-time binding


Download ppt "C++ Programming: Program Design Including Data Structures, Second Edition Chapter 13: Pointers, Classes, Lists, and Virtual Functions."

Similar presentations


Ads by Google