A first attempt at the Date class:
const int MAXLEN = 30;
class Date
{
public:
Date(int m, int d, int y, char* msg);
void Print(void) const;
private:
int month;
int day;
int year;
char message[MAXLEN];
};
Date::Date(int m, int d, int y, char* msg)
{
month = m;
day = d;
year = y;
if (strlen(msg) < MAXLEN)
strcpy(message, msg);
else
{
strncpy(message, msg, MAXLEN - 1);
message[MAXLEN - 1] = 0;
}
}
void Date::Print(void) const
{
cout << month << "/" << day << "/" << year << " : ";
cout << message << endl;
}
Classes and Dynamic Data - 2
A second attempt at the Date class:
class Date
{
public:
Date(int m, int d, int y, char* msg);
void Print(void) const;
private:
int month;
int day;
int year;
char* message;
};
Date::Date(int m, int d, int y, char* msg)
{
month = m;
day = d;
year = y;
message = new char[strlen(msg) + 1];
strcpy(message, msg);
}
void Date::Print(void) const
{
cout << month << "/" << day << "/" << year << " : ";
cout << message << endl;
}
In this implementation, we dynamically allocate memory for the message
array. Notice, however, that we do not provide a mechanism for
de-allocating that memory.
Classes and Dynamic Data - 3
A third attempt at the Date class:
class Date
{
public:
// constructor
Date(int m, int d, int y, char* msg);
// copy-constructor
Date(const Date& otherDate);
// deep copy operation
void CopyFrom(Date otherDate);
// destructor
~Date(void);
void Print(void) const;
private:
int month;
int day;
int year;
char* message;
};
As a rule of thumb: any class that dynamically allocates memory should
include a constructor, a destructor, a copy-constructor, and a deep copy
operation as public member functions.
Constructors and Destructors
Constructors
Destructor for Date class
The destructor for the Date class is trivial:
Date::~Date(void)
{
delete [] message;
}
Shallow Copy versus Deep Copy
The built-in assignment operator performs a shallow copy of one class object to another; the programmer does not have to write any special code A shallow copy copies only the class members, not any data pointed to by a member A deep copy duplicates both the class members and any data pointed to by a member; the programmer must write code to perform a deep copy (pages 996-997)
date1 = date2; // shallow copy (built-in)
date1.CopyFrom(date2); // deep copy (programmer code)
void Date::CopyFrom(Date otherDate)
{
month = otherDate.month;
day = otherDate.day;
year = otherDate.year;
delete [] message;
message = new char[strlen(otherDate.message) + 1];
strcpy(message, otherDate.message);
}
Class Copy-Constructors
Copy constructors are required when initializing one object by another. C++ defines initialization as:
Date date1 = date2;
return date1;
void Date::Date(const Date& otherDate)
{
month = otherDate.month;
day = otherDate.day;
year = otherDate.year;
message = new char[strlen(otherDate.message) + 1];
strcpy(message, otherDate.message);
}
The constructor does not use any keyword to indicate that it is a copy
constructor. The pattern of the parameters is what makes it a copy
constructor.
Allocating Class Objects Dynamicallyconst SomeClass& someObject // in general const Date& otherDate // in our Date class
Until now, all objects have been instantiated implicitly:
void SomeFunction(void)
{
// construct Date object
Date date1(4, 15, 1998, "My birthday");
date1.Print();
} // date1's destructor is called before function returns
It is possible, and quite common, to explicitly allocate the objects
dynamically:
void SomeFunction(void)
{
// object is created on the free store
Date* date1 = new Date(4, 15, 1998, "My birthday");
date1->Print();
// date1's destructor is called by delete
delete date1;
}