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
}
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));
}