Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
тех прог.doc
Скачиваний:
13
Добавлен:
14.11.2019
Размер:
3.59 Mб
Скачать

15.5.Статические члены класса

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

Программа 44. Размер класса и объектов класса

Перепишем функцию main программы 43 так, чтобы напечатать размер класса Date и размер объектов этого класса. Других изменений в программу 43 не вносим.

// Файл DateCl_3.cpp

/* Здесь поместить объявление класса Date и реализацию функций этого класса из программы 43 */

int main()

{

Date Studies(1, 9, 2005); // Некоторая дата

Date Today; // Сегодняшняя дата

cout << "\nsizeof(Date) = " << sizeof(Date); // Размер класса

cout << "\n sizeof(Today) = " << sizeof(Today); // Размер объекта

Studies.Print(); cout << endl; // Вывод некоторой даты

Today.Print(); cout << endl; // Вывод текущей даты

getch();

return 0;

}

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

sizeof(Date) = 6

sizeof(Today) = 6

1.9.2005

4.4.2006

Видно, что размер класса и размер объектов класса одинаковы и равны 6 байт, так как класс состоит из трех переменных типа int, а в той системе, где выполнялась программа, размер int равен 2 байтам. Функции-члены класса не влияют на размер объектов класса. Они существуют в единственном экземпляре на весь класс, за исключением встроенных функций. Принадлежность функции к классу означает лишь возможность ее доступа к членам класса без явного указания этих членов как аргументов функции.

Заметим, что в различных реализациях размер целых типов может различаться, конкретный размер любого типа можно узнать с помощью оператора sizeof.

Есть возможность иметь в одном экземпляре на весь класс не только функции-члены, но и переменные-члены класса. Это реализуется с помощью статических членов.

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

15.6.Друзья класса

Закрытые члены класса недоступны для посторонних функций, но иногда требуется открыть доступ к ним для функций, которые не являются членами класса. Такие функции надо объявить в классе с ключевым словом friend (друг). В следующей программе это функция:

bool leapyear(Date dt){ return leap(dt.y); }

которая обращается к закрытому свойству y даты dt и передает его значение функции leap. Для високосного года leap возвратит 1, а leapyear – true, для невисокосного leap возвратит 0, а leapyear, соответственно, false.

Программа 45. Статические члены и друзья класса

Объявим класс дат в следующем виде:

// Файл DateCl_4.cpp

class Date{

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

static int d0, m0, y0; // Начальная дата

static int dw0; // День недели начальной даты,

// 1 - понедельник, 2 - вторник,...

public:

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

void Print();

// Функция установки начальной даты

static void SetInitialDate(int di, int mi, int yi, int dwi)

{

d0 = di; m0 = mi; y0 = yi; dw0 = dwi;

}

int DayOfYear(); // Номер дня в году

int NumberDayOfWeek(); // Номер дня недели

friend bool leapyear(Date ); // Объявление функции-друга

};

Из программы 43 вставляем конструктор класса, функцию Date::Print(), таблицу дней в месяцах daytab и функцию leap().

Функция DayOfYear() возвращает номер дня в году. Например, 28 февраля – это 59-й день года, а 1 марта, это 60-й день невисокосного и 61-й день високосного года.

int Date::DayOfYear() // Возвращает номер дня в году

{

int days = d; // Количество дней от начала месяца

int lp = leap(y); // Признак високосности года

for(int i = 1; i < m; i++)

days += daytab[lp][i];

return days;

}

Функция NumberDayOfWeek() возвращает номер дня недели для произвольной даты. Считаем, что понедельник – это 1-й день, вторник – второй, …, воскресенье – 7-й. Алгоритм расчета состоит в следующем. Находится число дней, прошедших от понедельника той недели, на которую приходится начальная дата. Эта величина складывается из числа дней, прошедших до конца начального года, числа дней в целых годах, прошедших между начальной и конечной датами и числом дней, прошедших от начала года до заданной даты. Находится остаток от деления найденного числа дней на 7. Если остаток – 0, значит, заданная дата приходится на понедельник. Чтобы получить номер дня, к остатку прибавляется 1.

int Date::NumberDayOfWeek() // Возвращает номер дня недели

{ // Понедельник - 1

Date dti(d0, m0, y0); // Начальная дата формируется по

// статическим членам класса

long days = dw0 - 1; // Количество дней, прошедших от

// понедельника начальной недели

days += 365 + leap(y0) - dti.DayOfYear(); // Учет дней в начальном году

for(int i = y0 + 1; i < y ; i++) // Учет дней

days += 365 + leap(i); // в промежуточных годах

days += DayOfYear(); // Учет дней в заданном году

return days % 7 + 1;

}

Внутри класса статические члены только объявляются, при этом память под них не выделяется, поэтому статические члены следует определить вне класса, чтобы под них была выделена память. При определении следует указывать имя класса.

// Определение статических членов класса

int Date::d0, Date::m0, Date::y0, Date::dw0;

Начальная дата устанавливается с помощью вызова статической функции SetInitialDate. В качестве квалификатора имени статической функции можно указываться имя класса, вместо имени объекта класса, как это делается для обычной функции.

// Определение функции-друга

bool leapyear(Date dt){ return leap(dt.y); }

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

#include <conio.h>

int main()

{

char* DayWeek[7] = { "Понедельник", "Вторник",

"Среда", "Четверг", "Пятница",

"Суббота", "Воскресенье"

};

// Вызов статической функции класса

Date::SetInitialDate(31, 12, 1599, 5); // 31 декабря 1599 г.

// была пятница

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

cout << "\nСегодня "; Today.Print(); // Вывод даты

// Вывод дня недели

cout << ", "<< DayWeek[Today.NumberDayOfWeek() - 1];

cout << ”\n Идет високосный год: ” << leapyear(Today);

getch();

return 0;

}

Программа выдает следующее:

Сегодня 25.11.2006, Суббота

Идет високосный год: 0

С помощью календаря убеждаемся в правильности результата.