1 Chapter 8 Destructor & Operator Overloading. 2 Destructor A destructor is a function that is...

35
1 Chapter 8 Destructor & Operator Overloading

Transcript of 1 Chapter 8 Destructor & Operator Overloading. 2 Destructor A destructor is a function that is...

1

Chapter 8

Destructor & Operator Overloading

2

Destructor A destructor is a function that is called

when an object is no longer required. A constructor is a function which is called

when a new object is created. A constructor is usually used to initiate an

object. A destructor is usually used to destroy an

object, This is necessary, when some data members are

dynamically allocated. (See Chapter 4)

3

Dynamic Memory Allocation (P.194) Sometimes depending on the input data, you

may allocate different amount of space for storing different types of variables at execution timeint n = 0;

cout << "Input the size of the vector - ";

cin >> n;

int vector[n];error C2057: expected constant expression

4

Free Store (Heap) To hold a string entered by the user, there

is no way you can know in advance how large this string could be.

Free Store - When your program is executed, there is unused memory in your computer.

You can dynamically allocate space within the free store for a new variable.

5

The new Operator Request memory for a double variable, and ret

urn the address of the space double* pvalue = NULL; pvalue = new double;

Initialize a variable created by new pvalue = new double(9999.0);

Use this pointer to reference the variable (indirection operator) *pvalue = 1234.0;

6

The delete Operator When you no longer need the (dynamically all

ocated) variable, you can free up the memory space. delete pvalue;

Release memory pointed to by pvalue pvalue = 0;

Reset the pointer to 0

After you release the space, the memory can be used to store a different variable later.

7

Allocating Memory Dynamically for Arrays Allocate a string of twenty characters

char* pstr; pstr = new char[20]; delete [] pstr;

Note the use of square brackets to indicate that you are deleting an array.

pstr = 0; Set pointer to null

9

The Default Destructor The destructor for a class is a member functio

n with the same name as the class, preceded by a tilde (~). For the CBox class, the prototype of the clas destru

ctor is ~CBox(); A destructor has no parameters.

Ex8_01.cpp on P.410 ~CBox(){cout << “Destructor called.” << endl;

}

10

Class CMessage (1) Suppose you want to define a class

Each object contains a text string. You don’t want to declare a data member as a large charact

er array (like char [200]), So you’ll allocate memory in the free store for the message

when an object is created. This is your constructor:

CMessage(const char* text = “Default message”)

{

pmessage = new char[strlen(text) + 1];

strcpy(pmessage, text);

}

11

strlen, strcmp, strcpy#include <iostream>#include <cstring>using std::cout;using std::endl;

int main(){

char a[20] = "NCNU";char b[20] = "Sunday";

cout << sizeof a << " " << strlen(a) << endl;// size = 20, string length = 4

if (strcmp(a,b) < 0)cout << "The string " << a

<< " is less than " << b << endl;

strcpy(a, b);cout << a << endl;

}

12

Destructors and Dynamic Memory Allocation

CMessage(const char* text = “Default message”)

{

pmessage = new char[strlen(text) + 1];

strcpy(pmessage, text);

}

~CMessage()

{

cout << “Destructor called.” << endl;

delete [] pmessage;

}

13

Ex8_02.cpp on P.413 As the output indicates, the destructor is calle

d only once. The object motto is created automatically, so the c

ompiler also calls the destructor automatically. If you manually “delete pM”, it will free the mem

ory pointed to by pM. Because the pointer pM points to a CMessage objec

t, this causes the destructor to be invoked.

14

Behavior of a Default Copy ConstructorCMessage motto1(“Radiation fades your genes.”);

CMessage motto2(motto1); // Calls default copy constructor

15

Q: What will the second motto2.ShowIt() display?CMessage motto1(“A stitch in time saves nine.”);

CMessage motto2(motto1);

motto2.ShowIt(); // Display 2nd message

strcpy(motto1.pmessage, "Time and tide wait for no man.");

motto1.ShowIt(); // Display 1st message

motto2.ShowIt(); // Display 2nd message

16

Implementing a Copy Constructor We don’t want the two objects sharing the same stri

ng in the memory. If motto1 is destroyed, the pointer in motto2 will beco

me invalid. Let us implement a copy constructor to generate an o

bject which is identical but independent of the old one.

CMessage(const CMessage& initM){

pmessage = new char [ strlen(initM.pmessage) +1 ];strcpy(pmessage, initM.pmessage);

}Exercise: Modify Ex8_02.cpp to implement this copy constructor.

17

Operator Overloading Operator overloading is a very important

capability. It allows you to make standard C++ operators, such as

+, -, * and so on, work with objects of your own data types.

We want to write if (box1 > box2)

instead of if (IsGreaterThan(box1, box2))

Let us recall some background of function overloading (Chapter 6).

18

Function Overloading Function overloading allows you to use the same func

tion name for defining several functions as long as they each have different parameter lists.

When the function is called, the compiler chooses the correct version according to the list of arguments you supply.

The following functions share a common name, but have a different parameter list: int max(int array[], int len); long max(long array[], int len); double max(double array[], int len);

19

Ex6_07.cpp on P.293 Three overloaded functions of max() In main(), C compiler inspect the argument

list to choose different version of functions.

20

Signature The signature of a function is determined by its name

and its parameter list. All functions in a program must have unique signature

s

The following example is not valid overloading double max(long array[], int len); long max(long array[], int len);

A different return type does not distinguish a function, if the signatures are the same.

21

Implementing an Overloaded Operator

class CBox

{

public:

bool operator> (CBox& aBox) const;

} The word operator here is a keyword. You declare the operator>() function as con

st because it doesn’t modify any data members of the class. (P.369)

22

Using an Overloaded Operator if (box1 > box2)

cout << “box1 is greater than box2”; if (box1.operator>(box2))

V

23

Ex8_03.cpp on P.422bool CBox::operator> (CBox& aBox) const

{

return this->Volume() > aBox.Volume();

}

The left operand is defined implicitly by the pointer this.

The basic > operator returns a value of type int 1 for true 0 for false.

It will be automatically converted to bool.

24

Overloading the Assignment Operator What’s wrong with the default

assignment? It simply provides a member-by-member

copying process, similar to that of the default copy constructor.

They suffer from the same problem, when some data members are allocated dynamically.

25

Fixing the ProblemCMessage& operator= (const CMessage& aMess){

// Release memory for 1st operanddelete [] pmessage;pmessage = new char [ strlen(aMess.pmessage) + 1];

// Copy 2nd operand string to 1st

strcpy(this->pmessage, aMess.pmessage);

// Return a reference to 1st operandreturn *this;

}

26

Why Do You Need to Return Something? Consider this statement

motto1 = motto2 = motto3; The assignment operator is right-associative, s

o it translates into motto1 = (motto2.operator=(motto3)); motto1.operator=(motto2.operator=(motto3));

You must at least return a CMessage object.

27

Why Do You Need to Return a Reference? Consider another example

(motto1 = motto2) = motto3; This translates into

(motto1.operator=(motto2)) = motto3; If the return type is merely CMessage instead o

f a reference, a temporary copy of the original object is returned. Then you are assigning a value to a temporary obje

ct! Make sure that your return type is CMessage&.

28

Check Addresses, If Equal The first thing that the operator function does

is to delete the memory allocated to the first object, and reallocate sufficient memory to accommodate the new string.

What happens to this statement? motto1 = motto1

Add this checking:if (this == &aMess)

return *this;

29

Overloading the Addition Operator Suppose we define the sum of two CBox object as a CBo

x object which is large enough to contain the other two boxes stacked on top of each other.

See Figure 8-4.

CBox CBox::operator+(const CBox& aBox) const{return CBox(m_Length > aBox.m_Length ? m_Length : aBox.m_Length,m_Width > aBox.m_Width ? m_Width : aBox.m_Width,M_Height + aBox.m_Height);}

Ex8_06.cpp on P.434

30

Using Classes We want to pack candy into candy boxes, and

pack candy boxes to cartons. The objects candy, candybox, carton, all belon

g to the CBox class. We are packing CBox objects into other CBox o

bjects.

31

Basic Operations of the CBox Class Calculate the volume of a CB

ox Volume()

Compare the volumes of two CBox objects to determine which is the larger. operator>()

Compare the volume of a CBox object with a specified value We have this for the > operat

or (P.414) Add two CBox object to prod

uce a CBox object operator+()

Multiply a CBox object by an integer to provide a CBox object

Determine how many CBox objects of a given size can be packed in another CBox object of a given size. This is effectively division, so

you could implement this by overloading the / operator.

Determine the volume of space remaining in a CBox object after packing it with the maximum number of CBox objects of a given size. Wasted spaced.

32

The Multiply Operation If n is even, stack the bo

xes side-by-side by doubling the m_Width value and only multiplying the m_Height value by half of n.

33

// CBox multiply operator this*n

CBox operator*(int n) const

{

if (n % 2)

return CBox(m_Length, M_Width, n*m_Height); // n odd

else

return CBox(m_Length, 2.0*m_Width, (n/2)*m_Height); // n even

}

34

The Division Operation Correct some mistakes in Figure 8-7.

L=3L=8

35

Member Function operator/() P.451int operator/(const CBox& aBox){

int tc1 = 0;int tc2 = 0;

tc1 = static_cast<int>((m_Length / aBox.m_Length)) *static_cast<int>((m_Width / aBox.m_Width));

tc2 = static_cast<int>((m_Length / aBox.mWidth)) *static_cast<int>((m_Width / aBox.m_Length));

return static_cast<int>((m_Height/aBox.m_Height)*(tc1>tc2 ? tc1 : tc2));

}

36

Member Function operator%() It would be easy to check the remaining space

using the functions you have already defined:

// Operator to return the free volume in a packed CBox

double operator%( const CBox& aBox, const CBox& bBox)

{

return aBox.Volume() - (aBox / bBox) * bBox.Volume();

}