Date Class Implementation
A comprehensive Date class demonstrates fundamental C++ concepts including default member functions and operator overloading. The implemantation requires the following components:
- Constructors and destructor
- Copy constructor and assignment operator
- Comparison operators (==, !=, >, <, >=, <=)
- Arithmetic operators (+, -, +=, -=)
- Increment/decrement operators (prefix/postfix ++, --)
- Date subtraction returning day count
// Calculate days in specific month/year
int Date::DaysInMonth(int yr, int mo) {
int monthDays[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
if (mo == 2 && ((yr % 4 == 0 && yr % 100 != 0) || (yr % 400 == 0))) {
return 29;
}
return monthDays[mo];
}
// Parameterized constructor
Date::Date(int yr, int mo, int dy) : year(yr), month(mo), day(dy) {}
// Copy constructor
Date::Date(const Date& other) : year(other.year), month(other.month), day(other.day) {}
// Assignment operator
Date& Date::operator=(const Date& other) {
year = other.year;
month = other.month;
day = other.day;
return *this;
}
// Destructor
Date::~Date() {
year = month = day = 0;
}
// Addition assignment operator
Date& Date::operator+=(int days) {
if (days < 0) return *this -= (-days);
day += days;
while (day > DaysInMonth(year, month)) {
day -= DaysInMonth(year, month);
month++;
if (month > 12) {
year++;
month = 1;
}
}
return *this;
}
// Addition operator
Date Date::operator+(int days) {
Date result(*this);
result += days;
return result;
}
// Subtraction operator
Date Date::operator-(int days) {
Date result(*this);
result.day -= days;
while (result.day <= 0) {
result.month--;
result.day += DaysInMonth(result.year, result.month);
if (result.month < 1) {
result.year--;
result.month = 12;
}
}
return result;
}
// Subtraction assignment operator
Date& Date::operator-=(int days) {
if (days < 0) return *this += (-days);
day -= days;
while (day <= 0) {
month--;
day += DaysInMonth(year, month);
if (month < 1) {
year--;
month = 12;
}
}
return *this;
}
// Prefix increment
Date& Date::operator++() {
return *this += 1;
}
// Postfix increment
Date Date::operator++(int) {
Date temp(*this);
*this += 1;
return temp;
}
// Prefix decrement
Date& Date::operator--() {
return *this -= 1;
}
// Postfix decrement
Date Date::operator--(int) {
Date temp(*this);
*this -= 1;
return temp;
}
// Comparison operators
bool Date::operator>(const Date& other) const {
return (year > other.year) ||
(year == other.year && month > other.month) ||
(year == other.year && month == other.month && day > other.day);
}
bool Date::operator==(const Date& other) const {
return year == other.year && month == other.month && day == other.day;
}
bool Date::operator<(const Date& other) const {
return !(*this >= other);
}
bool Date::operator>=(const Date& other) const {
return !(*this < other);
}
bool Date::operator<=(const Date& other) const {
return !(*this > other);
}
bool Date::operator!=(const Date& other) const {
return !(*this == other);
}
// Date difference in days
int Date::operator-(const Date& other) const {
int sign = 1;
Date later = *this;
Date earlier = other;
if (*this < other) {
later = other;
earlier = *this;
sign = -1;
}
int dayCount = 0;
while (earlier != later) {
++earlier;
++dayCount;
}
return sign * dayCount;
}
void Date::Display() const {
std::cout << year << "/" << month << "/" << day << std::endl;
}
Member Initialization Lists
Initialization lists provide the only mechanism for true member initialization in constructors:
class Date {
public:
Date(int yr, int mo, int dy)
: year(yr), month(mo), day(dy) { // Initialization list
}
private:
int year = 1900; // Default value
int month = 1;
int day = 1;
};
Key initialization list rules:
- Initialization order follows member declaration order, not list order
- Constructor parameters override default values when provided
- const members, reference members, and custom types without default constructors require initialization lists
- The
explicitkeyword prevents implicit constructor conversions
Static Class Members
Static members belong to the class itself rather than individual objects:
class Date {
public:
static int InstanceCount() { // Static member function
return objectCount;
}
private:
static int objectCount; // Static member declaration
};
int Date::objectCount = 0; // Static member definition
Static member characteristics:
- Shared across all class instances
- Accessed via class name or object reference
- Static variables require external definition
- Static functions lack
thispointer and can only access static members - Access modifiers apply to static members
Friend Functions and Classes
Friend declarations grant external functions/classes access to private members:
class Date {
friend class Calendar; // Friend class declaration
friend void PrintDate(const Date& d); // Friend function
};
Friend relationships are:
- Unidirectional (Date friends can access Date, not vice versa)
- Not transitive (friends of friends have no special access)
- Not inherited by derived classes
- Cannot be declared with
constqualifier
Nested Classes
Classes defined within other classes establish special relationships:
class Calendar {
class DateIterator { // Nested class
public:
void AccessCalendar() { // Can access Calendar's private members
// Implementation
}
};
};
Nested class properties:
- Automatically friends of enclosing class
- Can access all enclosing class members
- Enclosing class cannot access nested class private members
- Sizeof(enclosing class) excludes nested class size
- Classes are types and don't allocate memory until instantiated