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:
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.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; }
Classes and Dynamic Data - 3
A third attempt at the Date class:
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.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; };
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;
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.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); }
Allocating Class Objects Dynamicallyconst SomeClass& someObject // in general const Date& otherDate // in our Date class
Until now, all objects have been instantiated implicitly:
It is possible, and quite common, to explicitly allocate the objects dynamically:void SomeFunction(void) { // construct Date object Date date1(4, 15, 1998, "My birthday"); date1.Print(); } // date1's destructor is called before function returns
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; }