chapter 15 pointers, classes, and virtual functions

33
CHAPTER 15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

Upload: oona

Post on 02-Feb-2016

66 views

Category:

Documents


1 download

DESCRIPTION

CHAPTER 15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS. 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 - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

CHAPTER 15

POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

Page 2: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

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 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 Examine the relationship between the address of

operator and classes

Page 3: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

THE POINTER DATA TYPE AND POINTER VARIABLES Pointer variable: A variable whose content is an address— (that is, a memory address).

int *p;

char *ch;

The statement

int *p; is equivalent to int* p; is equivalent to int * p;

The character * can appear anywhere between the data type name and the variable name.

int* p, q;

Only p is the pointer variable, not q. Here q is an int variable. To avoid confusion, we prefer to 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;

THE ADDRESS OF OPERATOR (&) In C++, the ampersand, &, called the address of operator, is a unary operator that returns the address of its operand.

int x;

int *p;

p = &x;

assigns the address of x to p. That is, x and the value of p refers to the same memory location.

Page 4: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

THE DEREFERENCING OPERATOR (*) C++ also uses * as a unary operator. When used as a unary operator, *, commonly referred to as the dereferencing operator or indirection operator, refers to the object to which its operand (that is, a pointer) points

int x = 25;

int *p;

p = &x; //store the address of x in p

cout<<*p<<endl; //prints the value of x. Also the statement

*p = 55; //will store 55 in the memory location pointed to by p, that is, in x. int *p;

int num= 78;

•p is a pointer variable of the type int and num is a variable of type int.

Page 5: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

p = &num;

*p = 24;

Page 6: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

Example 15-2#include <iostream>

using namespace std;

int main(){ int *p; int x = 37;

cout<<"Line 1: x = "<<x<<endl; //Line 1

p = &x; //Line 2

cout<<"Line 3: *p = "<<*p <<", x = "<<x<<endl; //Line 3

*p = 58; //Line 4

cout<<"Line 5: *p = "<<*p <<", x = "<<x<<endl; //Line 5

cout<<"Line 6: Address of p = "<<&p<<endl; //Line 6

cout<<"Line 7: Value of p = "<<p<<endl; //Line 7 cout<<"Line 8: Value of the memory location "

<<"pointed to by *p = "<<*p<<endl; //Line 8 cout<<"Line 9: Address of x = "<<&x<<endl; //Line 9 cout<<"Line 10: Value of x = "<<x<<endl; //Line 10

return 0;}

Line 1: x = 37Line 3: *p = 37, x = 37Line 5: *p = 58, x = 58Line 6: Address of p = 006BFDF4Line 7: Value of p = 006BFDF0Line 8: Value of the memory location pointed to by *p = 58Line 9: Address of x = 006BFDF0Line 10: Value of x = 58

Page 7: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

CLASSES, STRUCTS, AND POINTER VARIABLES You can also declare pointers to other data types, such as classes and structs.

struct studentType{ char name[26]; double gpa; int ssn; char grade;};

studentType student;studentType* studentPtr;

studentPtr = &student;student.gpa = 3.9; (*studentPtr).gpa = 3.9;

store 3.9 in the component gpa of the object student.

Since dot has a higher precedence than the dereferencing operator, parentheses are important. C++ provides another operator, called the member access operator arrow, ->. The syntax for accessing a class (struct) member using the operator -> is

pointerVariableName->classMemberName

The following statements are equivalent.(*studentPtr).gpa = 3.9; studentPtr->gpa = 3.9;

Page 8: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

Example 15-3class classExample

{public: void setX(int a); void print() const;

private:int x;

};

void classExample::setX(int a)

{x = a;

}

void classExample::print() const{

cout<<"x = "<<x<<endl;}int main(){

classExample *cExpPtr; //Line 1classExample cExpObject; //Line 2

cExpPtr = &cExpObject; //Line 3

cExpPtr->setX(5); //Line 4cExpPtr->print(); //Line 5

return 0;}

Output

x = 5

Page 9: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

INITIALIZING POINTER VARIABLESp = NULL;

p = 0;

DYNAMIC VARIABLES Variables that are created during program execution are called dynamic variables.

With the help of pointers, C++ creates dynamic variables.

C++ provides two operators, new and delete, to create and destroy dynamic variables, respectively.

int *p;

char *q; int x;

• The statement

p = &x;

stores the address of x in p. No new memory is allocated.

p = new int;

creates a variable during execution somewhere in the memory, and stores the address of the allocated memory in p.

• The allocated memory is accessed via pointer dereferencing, *p.

q = new char[16];

creates an array of 16 components of the type char and stores the base address in q.

Page 10: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

int *p; //p is a pointer of the type int

char *name; //name is a pointer of the type char

string *str; //str is a pointer of the type string

p = new int;

*p = 28; //stores 28 in the allocated memory

name = new char[5];

strcpy(name, "John"); //stores John in name

str = new string; //allocates memory of the type string and stores

//the address of the allocated memory in str

*str = "Sunny Day"; //stores the string "Sunny Day" in memory pointed to by str

The C++ operator delete is used to destroy dynamic variables.

delete p; //to deallocate memory referenced by the pointer p

delete [] name; //to deallocate a dynamically created array pointed by name

Page 11: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

OPERATIONS ON POINTER VARIABLES

Assignment : Value of one pointer variable can be assigned to another pointer variable of the same type.

int *p, *q;

p = q;

copies the value of q into p,which means p and q is pointing to the same Memory location.

• Relational operations :Two pointer variables of the same type can be compared for equality, and so on.

p == q // evaluates to true if both p and q have the same value.

p != q // evaluates to true, if both p and q point to different memory locations

Page 12: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

OPERATIONS ON POINTER VARIABLES Some limited arithmetic operations.

int *p;double *q;char *chPtr;studentType *stdPtr; //studentType data type is as defined before

The memory allocated for an int variable is 4 bytes, a double variable is 8 bytes, and a char variable is 1 byte. The memory allocated for a variable of the type studentType is 39 bytes.

p++; or p = p+1; //increments the value of p by 4 bytes.

q++;

chPtr++; //increment the value of q by 8 bytes and the value of chPtr by 1 byte

stdPtr++; //increments the value of stdPtr by 39 bytes.

p = p + 2; //increments the value of p by 8 bytes.

Page 13: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

DYNAMIC ARRAYS An array created during the execution of a program is called a dynamic array. To create a dynamic array, we use the second form of the new operator.

int *p; //declares p to be a pointer variable of the type int. int arraySize;

cout<<"Enter array size: ";cin>>arraySize; // if user enter 10, arraySize will be 10

p = new int[arraySize];

allocates 10 contiguous memory locations, each of the type int, and stores the address of the first memory location into p.

*p = 25; // stores 25 into first memory location.p++;*p = 35; // stores 35 into the second memory location.

C++ allows us to use array notation to access these memory locations.

p[0] = 25;p[1] = 35;

for(j = 0; j < 10; j++)

p[j] = 0;

Page 14: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

int list[10];

list is the array name and also a constant pointer that point the first array component. Any attempt to use increment or decrement operation on list will result in compile time

error. If p is a pointer variable of the type int, then the statement

int *p; p = list;

copies the address value of list into p. We are allowed to perform increment and decrement operations on p.

for(j = 0; j < 10; j++) p[j] = 0;

for(j = 0; j < 10; j++) *(p + j) = 0;

for(j = 0; j < 10; j++) list[j] = 0;

for(j = 0; j < 10; j++) *(list + j) = 0;

for(p = list; p < list + 10; p++) *p = 0;

Page 15: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

Functions and Pointers A pointer variable can be passed as a parameter to a function either by value or by reference.

In C++, 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. The parameter p is a reference parameter; the parameter q is a value parameter.

Pointers and Function Return Value In C++, a function can return a value of the type pointer.

The return type of the function

int* testExp(...)

{

.

.

.

}

is a pointer of the type int.

Page 16: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

In a shallow copy, two or more pointers of the same type point to the same memory; that is, they point to the same data.

int *first;int *second;first = new int[10];

second = first;

delete [] second;

Page 17: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

second = new int[10];

for(int j = 0; j < 10; j++) second[j] = first[j];

• In a deep copy, two or more pointers have their own data.

Page 18: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

CLASSES AND POINTERS: SOME PECULIARITIESclass pointerDataClass{public: ...

private: int x; int lenP; int *p;};

pointerDataClass objectOne;pointerDataClass objectTwo;

pointerDataClass::~pointerDataClass(){

delete [] p;}

class pointerDataClass

{public: ~pointerDataClass();

...

private: int x; int lenP; int *p;};

Page 19: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

The Destructor The object objectOne has a pointer data member p. Suppose that during program execution the pointer p creates a dynamic array. When objectOne goes out of scope, all data members of objectOne are destroyed. However, p created a dynamic array, and dynamic memory must be deallocated using the

operator delete. If the pointer p does not use the delete operator to deallocate the dynamic array, the

memory space of the dynamic array would stay marked as allocated, even though no one can access it.

How do we ensure that when p is destroyed, the dynamic memory created by p is also destroyed?

If a class has a destructor, the destructor automatically executes whenever a class object goes out of scope. We can deallocate memory that was created by p the necessary code in the destructor to ensure that when objectOne goes out of scope, the memory created by the pointer is deallocated.

Page 20: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

The Assignment Operator

objectTwo = objectOne;

If objectTwo.p deallocates the memory space to which it points, objectOne.p would become invalid.

Page 21: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

To avoid this shallow copying of data for classes with a pointer data member, C++ allows the programmer to extend the definition of the assignment operator.

This process is called overloading the assignment(=) operator. (chap. 16) Once the assignment operator is properly overloaded, both the objects objectOne and objectTwo

have their own data, as shown in Figure 15-19.

The Copy ConstructorConsider the following statement:

pointerDataClass objectThree(objectOne);

The object objectThree is being declared and is also being initialized by using the value of objectOne. This initialization is called the default member-wise initialization. The default member-wise initialization is due to the constructor, called the copy constructor (provided by the compiler.) This default initialization would lead to a shallow copying of the data.

Page 22: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

void destroyList(pointerDataClass paramObject);

destroyList(objectOne);

pointerDataClass has pointer data members p:Call by value would create a copy of the actual parameter into the formal parameter, and the default member-wise copying of data is allowed, it would lead to shallow copying of data.We must override the definition of the copy constructor provided by the compiler.This is usually done by putting a statement that includes the copy constructor in the definition of the class, and then writing the definition of the copy constructor.

Page 23: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

The copy constructor automatically executes in two situations (as described in the previous list): When an object is declared and initialized by using the value of another

object When, as a parameter, an object is passed by value

Once the copy constructor is properly defined for the class pointerDataClass, both objectOne.p and objectThree.p will have their own copies of the data. Similarly, objectOne.p and paramObject.p will have their own copies of the data.

Page 24: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

Example 15-5 ptrDataClass.h

class pointerDataClass{public: void print() const; void setData(); void destroyP(); pointerDataClass(int sizeP = 10); ~pointerDataClass(); pointerDataClass (const pointerDataClass& otherObject); //the copy constructorprivate: int x; int lenP; int *p; //pointer to an int array};

void pointerDataClass::print() const{

cout<<"x = "<<x<<endl;

cout<<"p = ";

for(int i = 0; i < lenP; i++) cout<<p[i]<<" ";cout<<endl;

}

void pointerDataClass::setData(){

cout<<"Enter an integer for x: ";cin>>x;cout<<endl;

cout<<"Enter "<<lenP<<" numbers: ";

for(int i = 0; i < lenP; i++) cin>>p[i];

cout<<endl;}

Page 25: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

void pointerDataClass::destroyP(){

lenP = 0;delete [] p;p = NULL;

}

pointerDataClass::pointerDataClass(int sizeP){

x = 0;

if(sizeP <= 0){

cout<<"Array size must be positive"<<endl;cout<<"Creating an array of size 10"<<endl;

lenP = 10;}else

lenP = sizeP;

p = new int[lenP];} pointerDataClass::~pointerDataClass(){

delete [] p;}

//copy constructorpointerDataClass::pointerDataClass (const pointerDataClass& otherObject){

x = otherObject.x;

lenP = otherObject.lenP; p = new int[lenP];

for(int i = 0; i < lenP; i++) p[i] = otherObject.p[i];

}

Page 26: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

#include <iostream>#include "ptrDataClass.h”

using namespace std;

void testCopyConst(pointerDataClass temp);

int main(){

pointerDataClass one(5); //Line 1

one.setData(); //Line 2cout<<"Line 3: ###Object one's data###"<<endl; //Line 3one.print(); //Line 4cout<<"Line 5:____________________________________________"<<endl;//Line 5

pointerDataClass two(one); //Line 6

cout<<"Line 7: ^^^Object two's data^^^"<<endl; //Line 7two.print(); //Line 8cout<<"Line 9:____________________________________________"<<endl;//Line 9

two.destroyP(); //Line 10

cout<<"Line 11: ~~~ Object one's data after destroying object two.p ~~~"<<endl; one.print();//Line 12

cout<<"Line 13:____________________________________________"<<endl;//Line 13

cout<<"Line 14: Calling the function testCopyConst”<<endl;//Line 14

testCopyConst(one); //Line 15

cout<<"Line 16:____________________________________________"<<endl;//Line 16

cout<<"Line 17: After a call to the function testCopyConst, object oneis:"<<endl; //Line 17

one.print(); //Line 18

return 0; //Line 19}

Page 27: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

void testCopyConst(pointerDataClass temp){cout<<"Line 20: *** Inside function " <<"testCopyConst ***"<<endl; //Line 20

cout<<"Line 21: Object temp data:"<<endl; //Line 21temp.print(); //Line 22

temp.setData(); //Line 23cout<<"Line 24: After changing the object temp, its data is: "<<endl; //Line 24temp.print(); //Line 25

cout<<"Line 26: *** Exiting function testCopyConst ***"<<endl; //Line 26

}

Page 28: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

Sample Run: In this sample run, the user input is in red.

Enter an integer for x: 28

Enter 5 numbers: 2 4 6 8 10

Line 3: ###Object one's data###x = 28p = 2 4 6 8 10Line 5:____________________________________________Line 7: ^^^Object two's data^^^x = 28p = 2 4 6 8 10Line 9:____________________________________________Line 11: ~~~ Object one's data after destroying object two.p ~~~x = 28p = 2 4 6 8 10Line 13:____________________________________________Line 14: Calling the function testCopyConstLine 20: *** Inside function testCopyConst ***Line 21: Object temp data:x = 28p = 2 4 6 8 10Enter an integer for x: 65

Enter 5 numbers: 1 3 5 7 9

Line 24: After changing the object temp, its data is:x = 65p = 1 3 5 7 9Line 26: *** Exiting function testCopyConst ***Line 16:____________________________________________Line 17: After a call to the function testCopyConst, object one is:x = 28p = 2 4 6 8 10

Page 29: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

THE ADDRESS OF OPERATOR AND CLASSES The address of operator is also used to create aliases to an object.

Consider the following statements:

int x;

int &y = x;

Both 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.

Page 30: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

The address of operator, &, can also be used to return the address of private data members of a class. However, if we are not careful this can result in serious errors in the program.

//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

Page 31: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

//Implementation file testAdd.cpp#include <iostream>#include "testAdd.h"using namespace std;

void testAddress::setX(int inX){

x = inX;}

void testAddress::printX() const{

cout<<x;}

int& testAddress::addressOfX(){ return x;

}

Page 32: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

//Test program#include <iostream>#include "testAdd.h"using namespace std;

int main(){

testAddress a;int &y = a.addressOfX();

a.setX(50);cout<<"x in class testAddress = ";a.printX();cout<<endl;

y = 25;cout<<"After y = 25, x in class testAddress = ";a.printX();cout<<endl;

return 0;}

Outputx in class testAddress = 50After y = 25, x in class testAddress = 25

Page 33: CHAPTER  15 POINTERS, CLASSES, AND VIRTUAL FUNCTIONS

#ifndef H_testAdd#define H_testAdd

class testAddress{public: void setX(int); void printX() const; const int& addressOfX(); //this function returns the //address of the private data //memberprivate: int x;};#endif

const int& testAddress::addressOfX(){ return x;}

The definition of the function addressOfX in the implementation file is:

const int& testAddress::addressOfX(){ return x;}

The same program now will generate compile time error if we attempt to change the content of x through the alias.