Chapter 13 Pointers

Download Report

Transcript Chapter 13 Pointers

CHAPTER 14
POINTERS, CLASSES, LISTS,
AND VIRTUAL FUNCTIONS
THE POINTER DATA TYPE AND POINTER
VARIABLES
 Pointer variable: A variable whose content is an address— (that is,
a memory address).
Declaring Pointer Variables
 The general syntax of declaring a pointer variable is
dataType *identifier;
int
char
*p;
*ch;
 The statement
int
*p;
is equivalent to the statement
int*
p;
which is equivalent to the statement
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.
Given the statements
int x;
int *p;
the statement
p = &x;
assigns the address of x to p. That is, x and the value of p refers to
the same memory location.
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
The statement
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;
• p is a pointer variable of the type int and num is a variable of type int.
num = 78;
p = &num;
*p = 24;
1. &p, p, and *p all have different meanings.
2. &p means the address of p—that is, 1200 (in Figure 14-4).
3. p means the content of p (1800 in Figure 14-4).
4. *p means the content (24 in Figure 14-4) of the memory location
(1800 in Figure 14-4) pointed to by p (that is, pointed to by the
content of memory location 1200).
Example 14-1
int *p;
int x;
• After the statement
x
= 50;
• After the statement:
p = &x;
• After the statement
*p = 38;
1. A declaration such as
int *p;
allocates memory for p only, not for *p.
2. Assume the following:
int *p;
int x;
a. p is a pointer variable;
b. Content of p only points to a memory location of the type int;
c. Memory location x exists and is of the type int.
The assignment
p = &x;
is legal. After the execution of this statement *p is valid and
meaningful.
Example 14-2
//Chapter 14: Example 14-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;
cout<<"Line 9: Address of x = "<<&x<<endl;
cout<<"Line 10: Value of x = "<<x<<endl;
"
//Line 8
//Line 9
//Line 10
return 0;
}
Sample Run
Line
Line
Line
Line
Line
Line
Line
Line
1: x = 37
3: *p = 37, x = 37
5: *p = 58, x = 58
6: Address of p = 006BFDF4
7: Value of p = 006BFDF0
8: Value of the memory location pointed to by *p = 58
9: Address of x = 006BFDF0
10: Value of x = 58
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 sID;
char grade;
};
studentType
studentType
student;
*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;
Example 14-3
class 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;
classExample cExpObject;
//Line 1
//Line 2
cExpPtr = &cExpObject;
//Line 3
cExpPtr->setX(5);
cExpPtr->print();
//Line 4
//Line 5
return 0;
}
Output
x = 5
INITIALIZING POINTER VARIABLES
Because C++ does not automatically initialize
variables, pointer variables must be
initialized if you do not want to point to
anything.
Pointer variables are initialized using the
constant value 0, called the null pointer. You
can also use the constant NULL.
p = 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.
 When a program requires a new variable, the operator new is used;
when a program no longer needs a dynamic variable, the operator
delete is used.
 In C++, new and delete are reserved words.
 The syntax to use the operator new is
new dataType;
new dataType[intExp];
//to allocate a single variable
//to allocate an array of variables
where intExp is any expression evaluating to a positive integer.
 The operator new allocates memory (a variable) of the designated
type and returns a pointer to it—that is, the address of this allocated
memory.
 The allocated memory is uninitialized.
int *p;
char *q;
int x;
• The statement
p = &x;
stores the address of x in p. No new memory is allocated.
• The statement
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.
• The statement
q = new char[16];
creates an array of 16 components of the type char and stores the
base address in q.
int *p;
char *name;
string *str;
//p is a pointer of the type int
//name is a pointer of the type char
//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. The
syntax to use the operator delete has two forms:
delete pointer;
delete [] pointer;
//to destroy a single dynamic variable
//to destroy a dynamically created
//array
 The statements
delete p;
delete [] name;
deallocate memory referenced by the pointers p and name.
OPERATIONS ON POINTER VARIABLES
 Assignment
 Value of one pointer variable can be assigned to another
pointer variable of the same type.
 Relational operations
 Two pointer variables of the same type can be compared for
equality, and so on.
 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.
int *p, *q;
The statement
p = q;
copies the value of q into p.
The expression
p == q
evaluates to true if both p and q have the same value.
The expression
p != q
evaluates to true, if both p and q point to different memory locations.
 Arithmetic operations, that are allowed, differ from the arithmetic
operations on numbers.
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.
 The statement
p++;
or
p = p+1;
increments the value of p by 4 bytes.
 The statements
q++;
chPtr++;
increment the value of q by 8 bytes and the value of chPtr by 1 byte
 The statement
stdPtr++;
increments the value of stdPtr by 39 bytes.
 The statement
p = p + 2;
increments the value of p by 8 bytes.
 When an integer is added to a pointer variable, the value of the
pointer variable is incremented by the integer times the size of the
memory that the pointer is pointing to.
 When an integer is subtracted from a pointer variable, the value
of the pointer variable is decremented by the integer times the
size of the memory to which the pointer is pointing.
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.
 The statement
int *p;
declares p to be a pointer variable of the type int.
 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.
 The statement
*p = 25;
stores 25 into the 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;
int list[10];
 list is a pointer variable.
 We always want list to point to 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
p = list;
copies the value of list into p. We are allowed to perform
increment and decrement operations on p.
 An array name is a constant pointer.
Example 14-4
int *intList;
int arraySize;
//Line 1
//Line 2
cout<<"Enter array size: ";
cin>>arraySize;
cout<<endl;
//Line 3
//Line 4
//Line 5
intList = new int[arraySize]; //Line 6





The statement at Line 1 declares intList to be a pointer of the type int
The statement at Line 2 declares arraySize to be an int variable.
The statement at Line 3 prompts the user to enter the size of the array.
The statement at Line 4 inputs the array size into the variable arraySize.
The statement at Line 6 creates an array of the size specified by
arraySize, and the base address of the array is stored in intList.
 From this point on, you can treat intList just like any other array. For
example, you can use the array notation to process the elements of
intList and pass intList as a parameter to the function.
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.
SHALLOW VERSUS DEEP COPY AND POINTERS
int *p;
p = new int;
 The first statement declares p to be a pointer variable of the type int.
 The second statement allocates memory of the type int, and the address of
the allocated memory is stored in.
*p = 87;
int *first;
int *second;
first = new int[10];
second = first;
//Line ***
delete [] second;
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.
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.
CLASSES AND POINTERS: SOME PECULIARITIES
class pointerDataClass
{
public:
...
private:
int x;
int lenP;
int *p;
};
pointerDataClass objectOne;
pointerDataClass objectTwo;
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 put the necessary code in the destructor to ensure that when
objectOne goes out of scope, the memory created by the pointer p is
deallocated.
pointerDataClass::~pointerDataClass()
{
delete [] p;
}
class pointerDataClass
{
public:
~pointerDataClass();
...
private:
int x;
int lenP;
int *p;
};
The Assignment Operator
objectTwo = objectOne;
 If objectTwo.p deallocates the memory space to which it points,
objectOne.p would become invalid.
 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.
 Chapter 15 explains how to accomplish this task by using operator
overloading.
 Once the assignment operator is properly overloaded, both the objects
objectOne and objectTwo have their own data, as shown in Figure 1419.
The Copy Constructor
 Consider 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.
void destroyList(pointerDataClass
destroyList(objectOne);
paramObject);
• Because objectOne is passed by value, the data members
of paramObject should have their own copy of the data. In
particular, paramObject.p should have its own memory
space.
• How do we ensure that this is , in fact, the case?
 If a class has pointer data members:
 During object declaration, the initialization of one object using the
value of another object would lead to shallow copying of data if
the default member-wise copying of data is allowed.
 If, as a parameter, 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, to force each object to have its own copy of the 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.
 For the class pointerDataClass, we can overcome this
shallow copying of data problem by including the copy constructor in
the class pointerDataClass.
 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.
• The general syntax to include the copy constructor in the
definition of a class is
className (const classname& otherObject);
Example 14-5
class pointerDataClass
{
public:
void print() const;
void setData();
void destroyP();
pointerDataClass(int sizeP = 10);
~pointerDataClass();
pointerDataClass (const pointerDataClass& otherObject);
//the copy constructor
private:
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;
}
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 constructor
pointerDataClass::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];
}
#include <iostream>
#include "ptrDataClass.h"
using namespace std;
void testCopyConst(pointerDataClass temp);
int main()
{
pointerDataClass one(5);
//Line 1
one.setData();
//Line 2
cout<<"Line 3: ###Object one's data###"<<endl; //Line 3
one.print();
//Line 4
cout<<"Line 5:______________________________"
<<"______________"<<endl;
//Line 5
pointerDataClass two(one);
//Line 6
cout<<"Line 7: ^^^Object two's data^^^"<<endl; //Line 7
two.print();
//Line 8
cout<<"Line 9:_______________________________"
<<"_____________"<<endl;
//Line 9
two.destroyP();
//Line 10
cout<<"Line 11: ~~~ Object one's data after "
<<"destroying object two.p ~~~"<<endl;
//Line 11
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 one is:"<<endl; //Line 17
}
one.print();
//Line 18
return 0;
//Line 19
void testCopyConst(pointerDataClass temp)
{
cout<<"Line 20: *** Inside function "
<<"testCopyConst ***"<<endl;
cout<<"Line 21: Object temp data:"<<endl;
temp.print();
//Line 21
//Line 22
temp.setData();
cout<<"Line 24: After changing the object "
<<"temp, its data is: "<<endl;
temp.print();
//Line 23
cout<<"Line 26: *** Exiting function "
<<"testCopyConst ***"<<endl;
}
//Line 20
//Line 24
//Line 25
//Line 26
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 = 28
p = 2 4 6 8 10
Line 5:____________________________________________
Line 7: ^^^Object two's data^^^
x = 28
p = 2 4 6 8 10
Line 9:____________________________________________
Line 11: ~~~ Object one's data after destroying object
two.p ~~~
x = 28
p = 2 4 6 8 10
Line 13:____________________________________________
Line 14: Calling the function testCopyConst
Line 20: *** Inside function testCopyConst ***
Line 21: Object temp data:
x = 28
p = 2 4 6 8 10
Enter an integer for x: 65
Enter 5 numbers: 1 3 5 7 9
Line 24: After changing the object temp, its data is:
x = 65
p = 1 3 5 7 9
Line 26: *** Exiting function testCopyConst ***
Line 16:____________________________________________
Line 17: After a call to the function testCopyConst,
object one is:
x = 28
p = 2 4 6 8 10
Array-Based Lists
List: A collection of elements of the same type. The length of
a list is the number of elements in the list.
Operations performed on a list are:
1. Create the list. The list is initialized to an empty state.
2. Determine whether the list is empty.
3. Determine whether the list is full.
4. Find the size of the list.
5. Destroy, or clear the list.
Operations performed on a list are:
6. Determine whether an item is the same as a given list
element.
7. Insert an item in the list at the specified location.
8. Remove an item from the list at the specified location.
9. Replace an item at the specified location with another
item.
10.Retrieve an item from the list at the specified location.
11.Search the list for a given item.
Lists are stored as an array. The size of the array can be specified when
a list object is declared.
To maintain and process the list in an array, we need three variables:
• The array holding the list elements
• A variable to store the length of the list (that is, the number of
elements currently in the array)
• A variable to store the size of the array (that is, the maximum
number of elements that can be stored in the array)
•
List Class definition
class arrayListType
{
bool isEmpty();
// Returns true if the list is empty
// otherwise, returns false.
bool isFull();
// Returns true if the list is full
// otherwise, returns false.
int listSize();
// Returns the size of the list, that is, the number
// of elements currently in the list.
int maxListSize();
//Returns the maximum size of the list, that is, the
//maximum number of elements that can be stored in
//the list.
void print() const;
//Outputs the elements of the list
bool isItemAtEqual(int location, int item);
//If the item is the same as the list element at the
//position specified by the location, returns true;
//otherwise, returns false.
•
List Class definition
void insertAt(int location, int insertItem);
//Inserts an item in the list at he specified location.
//The item to be inserted and the location are passed
//as parameters to the function
//If the list is full or the location is out of range,
//an appropriate message is displayed.
void insertEnd(int insertItem);
//Inserts an item at the end of the list. The item to
//be inserted is specified by the parameter insertItem.
void removeAt(int location);
//Removes the item from the list at the specified
//position. The location of the item to be removed is
//passed as a parameter to this function.
void retrieveAt(int location, int& retItem);
//Retrieves the element from the list at the position
//specified by the location. The item is returned via
//the parameter retItem.
void replaceAt(int location, int repItem);
//Replaces the element in the list at the position
//specified by the location. The item to be replaced is
//specified by the parameter repItem.
//If the list is full, an appropriate message is displayed
•
List Class definition
void clearList();
//All elements from the list are removed. After this
//operation, the size of the list is zero.
int seqSearch(int item);
//Searches the list for a given item. If the item is
//found, returns the location in the array where the
//item is found; otherwise, returns -1
void insert(int insertItem);
//The item specified by the parameter insertItem is
//inserted at the end of the list. However, the list
//is first searched to see whether the item to be
//inserted is already in the list. If the item is
//already in the list, an appropriate message is output.
void remove(int removeItem);
//Removes an item from the list. The item to be removed
//is specified by the parameter removeItem.
arrayListType(int size = 100);
//constructor
//Creates an array of the size specified by the
//parameter size. The default array size is 100.
•
List Class definition
arrayListType(const arrayListType& otherList);
//copy constructor
-arrayListType();
//destructor
//Deallocates the memory occupied by the array
protected:
int *list;
int length;
int maxSize;
};
//array to hold the list elements
//stores the length of the list
//stores the maximum size of the list
•
•
•
Data member length stores the number of elements currently in the list
Data member maxSize specifies the maximum size of the list
The list is empty if length is zero and full if length is equal to maxSize
Therefore definition of functions isEmpty, isFull, listSize and maxListSize are:
bool arrayListType::isEmpty()
{
return(length ==0);
}
bool arrayListType::isFull()
{
return(length ==maxSize);
}
int arrrayListType::listSize()
{
return length;
}
int arrrayListType::maxListSize()
{
return maxSize;
}
•
The function print outputs the elements of the list.
void arrayListType::print()const
{
int i;
for( i = 0; i < length; i++ )
cout<<list[i]<<“ “;
cout<<endl;
}
•
The definition of function isItemEqual
bool arrayListType::isItemEqual(int location, int item)
{
return(list[location] == item);
}
•
The function insertAt inserts an item at a specific location
void arrayListType::insertAt(int location, int insertItem)
{
int i;
if( location < 0 || 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 elements down
list[location] = insertItem; //inserts the item at the
//specified position
length++;
}
}//end insertAt
//increment the length
•
The function insertEnd inserts an item at the end of the array
void arrayListType::insertEnd(int insertItem)
{
if(length >= maxSize) // list is full
cout<<“Cannot insert in a full list”<<endl;
else
{
list[length] = insertItem; //inserts the item at the end
length++;
//increment the length
}//end insertEnd
•
•
•
The function removeAt removes an item from a specific location in
the list.
The location of the item to be removed is passed as a parameter.
After the item is removed the list is reduced by 1.
The function removeAt
void arrayListType::removeAt(int location)
{
int i;
if( location < 0 || location >= maxSize)
cout<<“The location of the item to be removed “
<<“is out of range”<<endl;
else
{
for( i = location; i < length; i++ )
list[i] = list[i+1];
length--;
}
}
•
The function retrieveAt
void arrayListType::retrieveAt(int location, int& retItem)
{
if( location < 0 || location >= length)
cout<<“The location of the item to be retrieved is“
<<“is out of range”<<endl;
else
retItem = list[location];
}
•
The function replaceAt
void arrayListType::replaceAt(int location, int& retItem)
{
if( location < 0 || location >= length)
cout<<“The location of the item to be replaced is“
<<“is out of range”<<endl;
else
list[location] = repItem;
}
•
•
The function clearList, removes the elements from the list, leaving
it empty
This is accomplished by setting data member length to zero
void arrayListType::clearList()
{
length = 0;
}
•
The constructor creates an array of the size specified by the user,
and initializes the length of the list to zero and maxSize to the size
specified by the user.
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];
}
•
The destructor
arrayListType::~arrayListType()
{
delete []list;
}
•
The copy constructor is called when an object is passed as a (value)
parameter to a function and when an object is declared and
initialized using the value of another object of the same type.
arrayListType::arrayListType(const arrayListType&
otherList)
{
int j;
maxSize = otherList.maxSize;
length = otherList.length;
list = new int[maxSize];
if( length != 0)
for(j=0; j<length; j++);
list[j] = otherList[j];
}
•
•
The function seqSearch is a linear or sequential search
The function seqSearch searches the list for a given item
int arrayListType::seqSearch(int item)
{
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;
}
•
•
The insert function inserts a new item in the list.
Call function seqSearch to search for duplicates
void arrayListType::insert(int insertItem)
{
int loc;
if(length == 0)
list[length++] = insertItem;
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;
}
}
•
•
The remove function deletes an item from the list.
Call function seqSearch to determine if the item is in the list
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 item to be deleted is not in the list.“
<<endl;
}
}
•
The following is the result of the sample run of the test program on page 711
Sample Run: In this sample run, the user input is shaded
Line 3: Enter numbers ending with –999
23 16 15 25 35 46 14 32 98 7 –999
Line 8: The list you entered is:
23 16 15 25 35 46 14 32 98 7
Line 10: The list size is: 10
Line 11: Enter the item to be deleted: 98
Line 15: After removing 98 the list is:
23 16 15 25 35 46 14 32 7
Line 16: The list size is: 9
Line 23: Inside the function testCopyConstructor.
23 16 15 25 35 46 14 32 7
Line 25: The list size is: 9
Line 19: The list after the copy constructor.
23 16 15 25 35 46 14 32 7
Line 21: The list size is: 9
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.
class baseClass
{
public:
void print();
baseClass(int u = 0);
private:
int x;
};
class derivedClass: public baseClass
{
public:
void print();
derivedClass(int u = 0, int v = 0);
private:
int a;
};
void baseClass::print()
{
cout<<"In baseClass x = "<<x<<endl;
}
baseClass::baseClass(int u)
{
x = u;
}
void derivedClass::print()
{
cout<<"In derivedClass ***: ";
baseClass::print();
cout<<"In derivedClass a = "<<a<<endl;
}
derivedClass::derivedClass(int u, int v)
: baseClass(u)
{
a = v;
}
void callPrint(baseClass& p)
{
p.print();
}
int main()
{
baseClass one(5);
derivedClass two(3, 15);
one.print();
two.print();
//Line 1
//Line 2
//Line 3
//Line 4
cout<<"*** Calling the function callPrint ***"
<<endl;
//Line 5
callPrint(one);
//Line 6
callPrint(two);
//Line 7
return 0;
}
Output
In baseClass x = 5
In derivedClass ***: In baseClass x = 3
In derivedClass a = 15
*** Calling the function callPrint ***
In baseClass x = 5
In baseClass x = 3
 In compile-time binding, the necessary code to call a specific
function is generated by the compiler.
 Compile-time binding is also known as static binding.
 For the statement in Line 7, the actual parameter is of the type
derivedClass.
 When the body of the function two executes, logically the print
function of object two should execute, which is not the case.
 C++ corrects this problem by providing the mechanism of virtual
functions.
 The binding of virtual functions occurs at program execution time, not
at compile-time.
 This kind of binding is called run-time binding.
 In run-time binding, the compiler does not generate code to call a
specific function; instead, it generates enough information to enable
the run-time system to generate the specific code for the appropriate
function call.
 Run-time binding is also known as dynamic binding.
virtual function
• A virtual function is a function member of a
class, declared using the "virtual" keyword.
A pointer to a derived class object may be
assigned to a base class pointer, and a
virtual function called through the pointer.
If the function is virtual and occurs both in
the base class and in derived classes, then
the right function will be picked up based
on what the base class pointer "really"
points at.
class baseClass
{
public:
virtual void print();
baseClass(int u = 0);
//virtual function
private:
int x;
};
class derivedClass: public baseClass
{
public:
void print();
derivedClass(int u = 0, int v = 0);
private:
int a;
};
 If we execute the previous program with these modifications, the
output is as follows.
Output
In baseClass x = 5
In derivedClass ***: In baseClass x = 3
In derivedClass a = 15
*** Calling the function callPrint ***
In baseClass x = 5
In derivedClass ***: In baseClass x = 3
In derivedClass a = 15
//Chapter 14: Virtual Functions
#include <iostream>
#include "classExtTestVirtual.h"
using namespace std;
void callPrint(baseClass *p);
int main()
{
baseClass *q;
derivedClass *r;
//Line 1
//Line 2
q = new baseClass(5);
r = new derivedClass(3,15);
//Line 3
//Line 4
q->print();
r->print();
//Line 5
//Line 6
cout<<"*** Calling the function callPrint ***"
<<endl;
//Line 7
callPrint(q);
//Line 8
callPrint(r);
//Line 9
return 0;
}
void callPrint(baseClass *p)
{
p->print();
}
Output
In baseClass x = 5
In derivedClass ***: In baseClass x = 3
In derivedClass a = 15
*** Calling the function callPrint ***
In baseClass x = 5
In derivedClass ***: In baseClass x = 3
In derivedClass a = 15
//Chapter 14: Virtual Functions and value parameters
#include <iostream>
#include "classExtTestVirtual.h"
using namespace std;
void callPrint(baseClass p);
int main()
{
baseClass one(5);
derivedClass two(3, 15);
one.print();
two.print();
//Line 1
//Line 2
//Line 3
//Line 4
cout<<"*** Calling the function callPrint ***"
<<endl;
//Line 5
callPrint(one);
//Line 6
callPrint(two);
//Line 7
return 0;
}
void callPrint(baseClass p) //p is a value parameter
{
p.print();
}
Output
In baseClass x = 5
In derivedClass ***: In baseClass x = 3
In derivedClass a = 15
*** Calling the function callPrint ***
In baseClass x = 5
In baseClass x = 3
 If a base class contains virtual functions, make the destructor of the
base class virtual.
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.
 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
//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;
}
//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;
}
Output
x in class testAddress = 50
After y = 25, x in class testAddress = 25
#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
//member
private:
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 errors.