2013-09-10 2 views
4

В настоящее время я пишу программу, в которой есть раздел, определяющий разницу в днях между двумя датами, но перегрузкой оператора минус.Перегрузка оператора '-'

В настоящее время я смотрю на свой экран, рисуя полный пробел. У меня в голове какие-то мимолетные мысли, но они точно такие, мимолетные.

Что произойдет в main.cpp, так это то, что будут две переменные, например beethovenDeathDate и beethovenBirthDate, которые будут вычтены для определения того, как долго он проживает. Если я правильно помню, это около 22000 дней.

Итак, без дальнейших церемоний, вот мой код:

Date.cpp

const std::string Date::MONTH_STRINGS[] = 
{ 
    "", //one based indexing 
    "January", 
    "February", 
    "March", 
    "April", 
    "May", 
    "June", 
    "July", 
    "August", 
    "September", 
    "October", 
    "November", 
    "December" 
}; 

const int Date::DAYS_PER_MONTH[] = 
{ 
    0, //one based indexing 
    31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 
};  

Date::Date(int day, int month, int year) : _year(year), _month(month), _day(day) 
{ 
    isValid(); 
} 

Date::Date() 
{ 
    time_t t = time(0); // get time now 
    struct tm * now = localtime(& t); 
    _year = now -> tm_year + 1900; 
    _month = now -> tm_mon + 1; 
    _day = now -> tm_mday; 
} 

int Date::maxDay(int month, int year) 
{ 
    int ret = DAYS_PER_MONTH[month]; 
    if(isLeapYear(year) == true && month == 2) 
    { 
     ++ret; 
    } 
    return ret; 
} 

void Date::addDay(bool forward) 
{ 
    if(forward) 
    { 
     if(_day < maxDay(_month, _year)) 
     { 
      ++_day; 
     } 
     else 
     { 
      _day = MIN_DAY; 
      ++_month; 
      if(_month > MAX_MONTH) 
      { 
       _month = MIN_MONTH; 
       ++_year; 
      }  
     } 
    } 
    else 
    { 
     if(_day <= MIN_DAY) 
     { 
      --_month; 
      if(_month < MIN_MONTH) 
      { 
       _month = MAX_MONTH; 
       --_year; 
      } 
      _day = maxDay(_month, _year); 
     } 
     else 
     { 
      --_day; 
     } 
    }  
} 


std::string Date::toString() const 
{ 
    if(isValid() == false) 
    { 
     return std::string(); 
    } 
    std::stringstream ss; 
    ss << MONTH_STRINGS[_month] << " " << _day << ", " << _year; 
    return ss.str();    
}  


bool Date::isValid() const 
{ 
    if(_month < MIN_MONTH || _month > MAX_MONTH) 
    { 
     std::cerr << "Invalid date " << std::endl; 
     return false; 
    } 
    int daysThisMonth = maxDay(_month, _year); 

    if(_day < MIN_DAY || _day > daysThisMonth) 
    { 
     std::cerr << "Invalid date " << std::endl;    
     return false; 
    } 
    return true; 
} 

bool Date::isLeapYear(int year) 
{ 
    if(!(year % 4)) 
    { 
     if(!(year % 100)) 
     { 
      if(!(year % 400)) 
      { 
       return true; 
      } 
      else 
      { 
       return false; 
      } 
     } 
     else 
     { 
      return true; 
     } 
    } 
    else 
    { 
     return false; 
    } 
} 

bool Date::isLeapYear() const 
{ 
    return isLeapYear(_year); 
} 

bool Date::isLeapDay() const 
{ 
    return isLeapDay(_day, _month, _year); 
} 

bool Date::isLeapDay(int day, int month, int year) 
{ 
    if(day == 29 && month == 2 && isLeapYear(year) == true) 
    { 
     return true; 
    } 
    else 
    { 
     return false; 
    } 
} 


void Date::addYears(int years) 
{ 
    if(years == 0) 
    { 
     return; 
    } 
    if(isLeapDay() && !isLeapDay(_day, _month, _year + years)) 
    { 
     _day = Date::DAYS_PER_MONTH[_month]; 
    } 
    _year += years; 
} 

void Date::addMonths(int months)  
{ 
    if(months == 0) 
    { 
     return; 
    } 
    int deltayears = months/MAX_MONTH; 
    int deltamonths = months % MAX_MONTH; 
    int newMonth = 0; 
    if(months > 0) 
    { 
     newMonth = (_month + deltamonths) % MAX_MONTH; 
     if((_month + deltamonths) > MAX_MONTH) 
     { 
      ++deltayears; 
     } 
    } 
    else 
    { 
     if((_month + deltamonths) < MIN_MONTH) 
     { 
      --deltayears; 
      newMonth = _month + deltamonths + MAX_MONTH; 
     } 
     else 
     { 
      newMonth = _month + deltamonths; 
     }  
    } 
    if(_day > maxDay(newMonth, _year + deltayears)) 
    { 
     _day = maxDay(newMonth, _year + deltayears); 
    } 
    _year += deltayears; 
    _month = newMonth; 

} 

void Date::addDays(int days) 
{ 
    if(days == 0) 
    { 
     return; 
    } 

    if(days < 0) 
    { 
     for(int i = 0; i > days; --i) 
     { 
      addDay(false); 
     } 
     return; 
    } 

    for(int i = 0; i < days; ++i) 
    { 
     addDay(true); 
    } 
} 

std::ostream& operator<<(std::ostream& os, const Date& date) 
{ 
    os << date.toString(); 
    return os; 
} 

Date Date::operator+(int days) const 
{ 
    Date ret = *this; 
    ret.addDays(days); 
    return ret; 
} 

Date& Date::operator+=(int days) 
{ 
    addDays(days); 
    return *this; 
} 
//This is where I get stumped (the parameters was just one of my failed experiments 
Date& Date::operator-(int day, int month, int year) 
{ 
} 
+1

Вы пытаетесь вычесть дни, месяц или годы с даты? Я спрашиваю, потому что в других перегруженных арифметических операциях у вас были только «дни» в качестве параметра. – smac89

+0

Ну, у двух есть разные цели. Я изучаю книгу прямо сейчас, и «назначение» требует перегружать + только для того, чтобы добавить две вещи вместе, где - вызвана экспликация, чтобы определить разницу в днях между двумя называемыми переменными. –

+1

Итак, если это так, вы хотите взять в качестве параметра объект даты и найти разницу в днях между двумя датами; в отличие от трех параметров, которые вы делаете. – smac89

ответ

2

Функция может быть записана либо в качестве члена или в качестве свободной функции. Функция-член подпись будет выглядеть следующим образом:

TimeDuration Date::operator-(Date const & rhs) const 

бесплатно функция будет выглядеть следующим образом:

TimeDuration operator-(Date const & lhs, Date const & rhs) 

TimeDuration здесь совершенно индивидуальный тип, представляющий собой отрезок времени. Если вы хотите, вы можете просто сделать это int, обозначающее количество дней, но было бы лучше, на мой взгляд, иметь более выразительный тип для этой цели. Независимо от того, что вы решите относительно типа возврата, для типа не имеет значения Date (и, конечно же, не Date&).

Возможным (хотя и не невероятно эффективная) реализация, учитывая, что вы уже написали функцию для добавления в день до даты, было бы что-то вроде этого:

if lhs_date comes before rhs_date 
    add days to (a copy of) lhs_date until lhs_date == rhs_date 
    return the negative of number of days added 
if rhs_date comes before lhs_date 
    add days to (a copy of) rhs_date until rhs_date == lhs_date 
    return the number of days added 
else 
    return 0 

Другая функция, которую вы могли бы хотеть (или, возможно, это то, что вы на самом деле хотели первоначально, но ваша формулировка не указывает на это) является функцией, которая может вычесть длительность времени от Date. В этом случае, возвращаемое значение будет другой Date объект (но не Date&), и возможные подписи будет выглядеть примерно так:

Date Date::operator-(TimeDuration rhs) const // member version 
Date operator-(Date const & lhs, TimeDuration const & rhs) // non-member version 
+1

@AndrewB Точно - 'lhs - rhs'. –

+0

Как заполнить функцию? Это в основном то, что меня тошнит на данный момент, однако получение надлежащей функции - это, безусловно, шаг в правильном направлении. Кроме того, я довольно новичок в C++, так где же «TimeDuration» происходит из вашего нижнего сценария? –

+1

@AndrewB Вы можете нормализовать все с точки зрения дней и выполнить разницу. – greatwolf

0

Вы должны сделать это:

//This is where I get stumped (the parameters was just one of my failed experiments 
TimeDuration& Date::operator-(Date const & d1) 
{ 
    // ... processing ... 
    // this - d1; 
} 

и назвать его как:

Date d1 = new Date(20, 01, 2013); 
TimeDuration duration = d1 - (new const Date(20, 01, 1922)); 
// Calculate no. of days or years using duration 

логика заключается в следующем:

  1. Проходит два Date объекты (первый может быть неявными) к функции перегрузки и возврат TimeDuration

  2. Для вызова этого оператора, вы можете создать Date объект с данными, которые у вас есть, вместо передачи каждого значение отдельно.

Пожалуйста, проверьте правильность синтаксиса.

+1

'Дата d1 = новая дата (...)'? Что это? Не C++, конечно. –

+0

@BenjaminLindley, ты прав. Вот почему я упомянул в конце своего ответа, чтобы проверить точный синтаксис.Решение, которое я предоставил, не является точным решением для копирования-вставки, это просто руководство для искателя правильной логики, которая должна идти в реализации. Пожалуйста, дайте мне знать, если вы найдете что-то неправильное в логике. –

Смежные вопросы