Implementing Date Class Operations and Advanced C++ Class Features

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 explicit keyword 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 this pointer 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 const qualifier

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

Tags: C++ Object-Oriented Programming Operator Overloading Class Design Static Members

Posted on Fri, 03 Jul 2026 16:04:35 +0000 by zak