Программа 46. модификация дат

В данной программе написаны функции для модификации даты, которые возвращают ссылку на измененную дату.

// Файл DateCl_6.cpp

class Date{

int d, m, y; // День, месяц и год

public:

Date(int = 0, int = 0, int = 0); // Конструктор

Date& Add_Year(int n); // Добавить к дате n лет

Date& Add_OneDay(); // Добавить к дате 1 день

Date& Add_Day(int n); // Добавить к дате n дней

Date& Add_OneMonth(); // Добавить к дате 1 месяц

Date& Add_Month(int n); // Добавить к дате n месяцев

void Print();

};

#include <iostream.h>

void Date::Print()

{

cout << d << '.' << m <<'.'<< y;

}

// leap: возвращает 1, если год year високосный и 0, если нет

int leap(int year)

{ return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0; }

Date& Date::Add_Year(int n)

{

if(m == 2 && d == 29 && leap(y + n) != 1){ m = 3; d = 1; }

y += n;

return *this; // Возвращаем ссылку на измененный объект

}

Здесь внутри функции Add_Year ключевое слово this имеет значение указателя на тот объект класса Date, для которого функция вызвана. Например, далее в main есть инструкция вызова функции Add_Year для объекта Studies:

Studies.Add_Year(4);

Здесь во время работы Add_Year указатель this имеет значение адреса переменной Studies, а выражение *this есть сам объект Studies.

// Массив дней в месяцах для невисокосного и високосного года

char daytab[2][13] ={{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},

{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}

};

Date& Date::Add_OneDay()

{

if(d < daytab[leap(y)][m]) // Не последний день месяца

d++;

else if(m < 12){ // Последний день месяца, но не последний года

d = 1; m++;

}

else{ // Последний день года

d = 1; m = 1; y++;

}

return *this;

}

Увеличение даты на n дней реализуется n-кратным вызовом функции увеличения даты на 1 день.

Date& Date::Add_Day(int n) // Добавить к дате n дней

{

for(int i = 0; i < n; i++) // Вызываем n раз функцию

Add_OneDay(); // увеличения даты на 1 день

return *this;

}

Если исходная дата приходится на декабрь, через месяц будет то же число января следующего года. Для 28, 29, 30 или 31 января, считаем, что через 1 месяц будет последнее число февраля. Последнее число следующего месяца будет также, если исходная дата – последнее число месяца, независимо от числа дней в месяцах.

Date& Date::Add_OneMonth() // Добавить к дате 1 месяц

{

if(m == 12){ // Если декабрь,то

m = 1; y++; // будет январь следующего года

}

else if((m == 1 && d > 28) || d == 31){ // Если январь, число > 28 или

// последний день промежуточного месяца,

m++; // наступит последнее число

d = daytab[leap(y)][m]; // следующего месяца

}

else

m++; // Следующий месяца

return *this;

}

Date& Date::Add_Month(int n) // Добавить к дате n месяцев

{

for(int i = 0; i < n; i++) // n раз

Add_OneMonth(); // добавляем по 1 месяцу

return *this;

}

// Реализация конструктора

#include <dos.h>

Date::Date(int dd, int mm, int yy)

{

date sysd; // Системная дата

getdate(&sysd); // Получение системной даты

d = dd ? dd : sysd.da_day;

m = mm ? mm : sysd.da_mon;

y = yy ? yy : sysd.da_year;

}

#include <conio.h>

int main()

{

Date Studies(1, 9, 2005);

cout << "Начало учебы: "; Studies.Print(); cout << endl;

Studies.Add_Year(4);

Studies.Add_Month(9);

Studies.Add_Day(21);

cout << "Конец учебы: "; Studies.Print(); cout << endl;

Date Today; // Использование конструктора по умолчанию, сегодня

cout << "Сегодня: "; Today.Print(); cout << endl;

Today.Add_Year(1).Add_Month(1).Add_Day(1);

cout << "Через 1 год, 1 месяц и 1 день будет ";

Today.Print(); cout << endl;

getch();

return 0;

}

Программа выдает:

Начало учебы: 1.9.2005

Конец учебы: 22.6.2010

Сегодня : 12.4.2006

Через 1 год 1 месяц 1 и один день будет 13.5.2007

Обсудим инструкцию

Today.Add_Year(1).Add_Month(1).Add_Day(1);

Когда есть несколько операторов точка (.), они выполняются слева направо, то есть приведенная инструкция эквивалентна следующей:

((Today.Add_Year(1)).Add_Month(1)).Add_Day(1);

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

Деструкторы

В конструкторах при создании объектов могут захватываться некоторые ресурсы, например, выделяться память, открываться файлы и т. п. При уничтожении объектов ресурсы должны освобождаться. Эту работу выполняют специальные функции-члены класса – деструкторы.

Имя деструктора совпадает с именем класса, только впереди добавляется знак ~ (тильда). Деструктор не имеет аргументов, и так же, как и конструктор, ничего не возвращает.

Деструкторы вызываются неявно, когда автоматическая переменная выходит из зоны видимости, когда оператором delete удаляется объект, созданный в свободной памяти оператором new.

Наши рекомендации