简体   繁体   中英

Creating a method that compares two objects

EDIT!!

I am teaching myself C++ and just learning about classes. To practice, I created a Date class with some methods. I am currently attempting to practice on this problem:

Use the Date class to create a method that compares two Date objects and returns the larger of the two.

So I already have some code and methods I made below. Here is where I am confused: When you call a method, its of this form: <object>.<method> . Say I have two Date objects date1 and date2 . I dont understand how to create a date method that takes two date objects because the method already is acting on one of objects. In other words, I would have expected to have something like this: date1.compareDate(date2) and this method would have returned the object that has a greater value. Can someone please explain how I do this problem?

I attempted to do this in my method: compareDate(). I made another method convert which creates an integer of the form YYYYMMDD and I can just use simple boolean logic to compare the greater value.

Please note I want to return the larger Date object and not a bool value.

Thank you in advance.

#include <iostream>
#include <iomanip>
using namespace std;

// Class declaration statement
class Date
{
    private:
        int month;
        int day;
        int year;
    public:

        Date(int = 7, int = 4, int = 2012); // Constructor
        void setDate(int, int, int);        // Member to copy a date
        void showDate();                    // Member method to display date
        int convert();
        bool leapYear();
        string dayOfWeek();
        void nextDay();
        void priorDay();
        Date compareDate(Date, Date);
};

// Class Implementation section
Date::Date(int mm, int dd, int yyyy)
{
    month = mm;
    day = dd;
    year = yyyy;
}

void Date::setDate(int mm, int dd, int yyyy)
{
    month = mm;
    day = dd;
    year = yyyy;
}

void Date::showDate()
{
    cout << "The date is ";
    cout << setfill('0')
         << setw(2) << month << '/'
         << setw(2) << day << '/'
         << setw(2) << year % 100;
    cout << endl;
}

int Date::convert()
{
    // Convert date to the integer format:  YYYYMMDD
    return year*10000 + month*100 + day;
}

bool Date::leapYear()
{
    if( (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0) )
        return true;
    else
        return false;
}

string Date::dayOfWeek()
{
    int dayInt;
    int mm, yyyy, dd, YYYY;
    int century, T, dayOfWeek;


    yyyy = year;
    mm = month;
    dd = day;

    if( mm < 3 )
    {
        mm = mm + 12;
        yyyy = yyyy - 1;
    }        

    century = int( yyyy/100 );
    YYYY = yyyy%100;

    T = dd + int( 26 * (mm + 1)/10) + YYYY + int(YYYY/4) + int( century/4)
        -2*century;

    dayOfWeek = T % 7;

    if( dayOfWeek < 0 )
        dayOfWeek += 7;

    if( dayOfWeek == 0 )
        return "Saturday";
    else if( dayOfWeek == 1)
        return "Sunday";
    else if( dayOfWeek == 2)
        return "Monday";
    else if( dayOfWeek == 3)
        return "Tuesday";
    else if( dayOfWeek == 4)
        return "Wednesday";
    else if( dayOfWeek == 5)
        return "Thursday";
    else if( dayOfWeek == 6)
        return "Friday";
    else
    {
        cout << "dayOfWeek = " << dayOfWeek << endl;
        return "Bad dayOfWeek Calc";
    }
}

void Date::nextDay()
{
    // Increment month and day if at 31 days in month
    // Skip December because have to increment year too
    if( (month == 1 || month == 3  || month == 5 || month == 7 || 
         month == 8 || month == 10) && day == 31 )
    {
        month++;
        day = 1;
    }
    // Increment month and day if at 30 days in month
    else if( (month == 4 || month == 6  || month == 9 || month == 11)
                && day == 30)
    {
        month++;
        day = 1;
    }
    // New year
    else if( month == 12 && day == 31 )
    {
        month = 1;
        day = 1;
        year++;
    }
    // Leap year
    else if( leapYear() && month == 2 && day == 29 )
    {
        month = 3;
        day = 1;
    }
    // Not leap year
    else if( !leapYear() && month == 2 && day == 28)
    {
        month = 3;
        day = 1;
    }
    // Regular day
    else
        day++;
}

void Date::priorDay()
{
    // Increment month and day if at 31 days in month
    // Skip December because have to increment year too
    if( (month == 5 || month == 7 || 
         month == 8 || month == 10 || month == 12) && day == 1 )
    {
        month--;
        day = 30;
    }
    // Increment month and day if at 30 days in month
    else if( (month == 2 || month == 4 || month == 6  || month == 9 || month == 11)
                && day == 1)
    {
        month--;
        day = 31;
    }
    // beginning year
    else if( month == 1 && day == 1 )
    {
        month = 12;
        day = 31;
        year--;
    }
    // Leap year
    else if( leapYear() && month == 3 && day == 1 )
    {
        month--;
        day = 29;
    }
    // Not leap year
    else if( !leapYear() && month == 3 && day == 1)
    {
        month--;
        day = 28;
    }
    // Regular day
    else
        day--;

}

Date Date::compareDate(Date date1, Date date2)
{
   // Return the greater date
    if( date1.convert() > date2.convert() )
        return date1;
    else
        return date2;
}


int main()
{
    Date c(4,1,2000);
    Date d(11, 1, 2013);
    b.setDate(12,25,2009);    

    cout << Date.compareDate(c,d) << endl;

    return 0;
}

You can compare your Date objects using operator (which you should write yourself)

friend bool operator> (const Date& D1, const Date& D2)
{
  return D1.convert() > D2.convert();
}

This operator is supposed to return true, if and only if D1 > D2. If this operator needs access to private parts of the Date object, then it must be declared as friend inside your Date class.

First of all, make all the functions that don't alter your class const:

int convert() const;

Add the following operator to your class:

bool operator< (const Date &other) const
{
    return convert() < other.convert();
}

Alexey's code would work too, but I prefer this one for two reasons: first, one shouldn't introduce friend functions whenever one can add member functions instead, and second, operator< is more important than operator> if you are going to use stl containers or algorithms. stl::set, stl::map, stl::sort all use operator<.

You can create a (freestanding) function that takes two Date s, as has been stated.

You can also create a Date method which ignores this , takes and compares two dates, and returns one of them. This is what you have done. But you still have to call this method through an instance. Also compensating for the lack of a << overload:

c.compareDate(c,d).showDate();

works. But of course it would be bad practice because you're asking for an instance ( c. ) where none is required.

What you were trying to do,

Date.compareDate(c,d)

suggests that you were looking for static methods. You need to declare them thus:

class Date {
    ...
    static Date compareDate(Date, Date);
};

and call them like this:

Date::compareDate(c,d).showDate();

(You also could also have a method, Date compareDate(Date) , that compares this to the parameter, but that would also be Bad.)

--

You should pick a better name for compareDate as it isn't currently clear that it's returning a brand new Date object.

Note that all the previous answers here (as well as the first version of mine) mistakenly thought you wanted to return bool . That's because that's how comparisons should be done, preferably with an operator< overload.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM