- •2 Программирование классов
- •Void Display(struct tTime tp)
- •Int year; //Данные-//члены
- •Int month; // -//-
- •Int hour; // -//-
- •Int minute; // -//-
- •Void Display(void); // Функция-// член
- •7: Int month; // “ “
- •9: Int hour; // “ “
- •10: Int minute; // “ “
- •3: #Ifndef time1_h
- •4: #Define time1_h 1
- •21: #Endif // _ _time1_h
- •Замечание
- •Типы доступа
- •Объект класса выходит
- •Объект конструктор требуемое количество функции-члены вызывается деструктор
- •Выделенную память
Int year; //Данные-//члены
Int month; // -//-
int day; // -//-
Int hour; // -//-
Int minute; // -//-
Void Display(void); // Функция-// член
};
Объявление класса очень похоже на объявление структуры TTime, исключая тот факт, что оно начинается с ключевого слова class.
Спецификатор доступа public открывает доступ ко всем членам, следующим за ним, для всех пользователей класса, поэтому такие члены называются открытыми.
Данные-члены в классах в точности такие же, как в данные-члены в структуре. Данные-члены, такие как year, month и day, могут быть переменными, указателями, ссылками, массивами, структурами и т.п. Они могут быть так же и объектами класса.
Конечно, члены не могут использовать спецификаторы классов памяти auto, extern или register.
Функции-члены класса, такие, как Display(), объявлены прототипами функций. Предположительно, функции-члены, подобные Display() в TTime, выполняет некоторые операции над данными-членами класса. Тело функции размещается в другом месте программы.
В листинге 2.1 используется класс TTime в программе на С++ и демонстрируется выполнение функции-члена.
Листинг 2.1. CLASS.CPP (класс TTime)
1: #include <iostream.h>
2: #include <stdio.h>
3:
4: class Ttime {
5: public: // спецификатор //доступа
6: int year; // данные-члены
7: Int month; // “ “
8: int day; // “ “
9: Int hour; // “ “
10: Int minute; // “ “
11: void Display(void);
// функция-член
12: };
13:
14: main()
15: {
16: Ttime app;
// Объект (экземпляр) типа //TTime
17:
//инициализация данных-членов
// объекта (Оператор точки следует //использовать для ссылок на открытые данные-//члены класса)
18: app . month = 7;
19: app. day = 14;
20: app . year = 1996;
21: app . hour = 8;
22: app . minute = 30;
23: cout << “App == ”;
24: app.Display();
// вызов функции-члена
25: cout << “/n”;
26: return 0;
27: }
28:
//реализация тела функции Display()
29: void Ttime ::Display(void)
30: {
31: char s[32];
32: sprintf(s, “date: %02d/%04d Ttime: %02d:%02d\n”,
33: month, day, year, hour, minute);
34: cout<< s;
35: }
В строках 4-12 объявляется класс TTime. Обычно объявления классов пишутся в заголовочных файлах
но можно вставить его непосредственно в программный модуль, как в этом примере.
В строках 29-35 приводится реализация тела функции Display().
Основные отличия между описанием функции-члена и обычной функции.
Имени функции-члена предшествует имя класса и оператор разрешения области видимости. Заголовок функции void TTime::Display(void) указывает компилятору, что Display() – член класса TTime.
Поскольку имя класса однозначно отождествляет имя функции-члена, в программе м.б. другие функции и функции-члены класса с именем Display(), не вызывающие конфликтов имен.
Внутри функции-члена операторы имеют прямой доступ к членам класса. Например, в строках 32-33 непосредственно используются данные-члены класса TTime – month, year, hour и minute.
В основной программе класс Ttime используется так же, как и любой другой тип данных.
Сначала в строке 16 объявляется appointment, как объект типа TTime. Объявления создает объект класса, так называемый экземпляр типа класса.
Класс TTime – всего лишь шаблон, схема, описывающая формат членов класса.
Вы должны создать объект типа класс, подобный appointment, для того, чтобы использовать класс.
Далее в строках 18-22 присваивают значения данным-членам appointment, инициализируются дата и время. Затем в строке 24, вызывается функция-член Display(), отображающая дату и время, хранящиеся в appointment.
Все эти строки используют оператор точки для доступа к членам объекта класса. Оператор точки следует использовать для ссылок на открытые данные-члены класса (которым предшествует спецификатор доступа public) аналогично ссылкам на члены структуры. Если таким членам является функции (см. строку 24), С++ вызывает функцию, которая обычно выполняет некоторые операции над данными-членами объекта класса. Например, в строке 24 вызывается функция Display() для отображения значения данных-членов appointment.
В программе также могут быть другие объекты класса Ttime, объявленные следующим образом:
TTime today;
TTime yesterday;
Этим объектам можно присвоить значения, и затем отобразить с помощью таких операторов:
today.Display(); //отображения значения объекта класса today
yesterday.Display();
// отображения значения объекта класса yesterday
С++ позволяет структурам и объединениям иметь функции-члены, подобно классам. Действительно, если вы замените class на struct и удалите спецификатор доступа public, программа будет работать, как раньше. (Члены структура или объединения по умолчанию открыты для доступа). Конечно, на практике функции-члены очень редко используются в структурах и объединениях и обычно объявляются в классах.
В листинге 2.2 объявляется новая улучшенная версия класса TTime, которая использует функции-члены для доступа к данным-членам класса. Новый класс облегчает изменение структуры данных-членов класса, что позволяет выдержать сроки проекта.
Листинг 2.2. CLASS.CPP (новая улучшенная версия класса TTime)
1: #include <iostream.h>
2: #include <stdio.h>
3:
4: class Ttime {
//спецификатор доступа делает //закрытыми в классе данные-члены в //строках 6-10
5: private:
6: int year;
7: int month;
8: int day;
9: int hour;
10: int minute;
11: public:
// открытые функции-члены
12: void Display(void);
13: void GetTime(int &m, int &d,
int &y, int &hr, int &min);
14: void SetTime(int m, int d, int y, int hr, int min);
15: };
16:
17: main()
18: {
19: Ttime ap;
20: int month, day, year, hour, minute;
21:
22: ap.SetTime(7,14, 1996, 8, 30);
23: cout<< “ap == ”;
24: ap.Display();
25: ap.GetTime(month, day, year, hour, minute);
26: ap.SetTime(month, day, year, ++hour, minute);
27: cout<< “next hour == ”;
28: ap .Display();
29: return 0;
30: }
31:
32: void Ttime::Display(void)
33: {
34: char s[32];
35: sprintf(s,“Date:%02d/%02d/%04d Time: %02d:%02d\n”,
36: month, day, year, hour, minute);
37: cout<< s;
38: }
39:
// передаются значения компонентов //объекта класса обратно, в аргументы //оператора вызова, путем использования
// целочисленных ссылочных параметров
40: void Ttime::GetTime(int &m, int &d, int &y, int &hr, int &min)
41: {
// Возвращение
//данных-членов тому, кто вызвал функцию
42: m= month;
43: d=day;
44: y=year;
45: hr=hour;
46: min=minute;
47: }
48:
// значения параметров присваиваются //данным-членам класса
49: void Ttime::SetTime(int m, int d, int y, int hr, int mint)
50: {
// Присваивание аргументов данным-//членам
51: month=m;
52: day=d;
53: year=y;
54: hour=hr;
55: minute=min;
56: }
закрытые (private) члены класса доступны только членам этого класса и никому более, закрытые члены невидимы вне класса.
В классе могут присутствовать многочисленные открытые и закрытые секции, располагающиеся в произвольном порядке. Можно повторять спецификаторы доступа private и public в объявлении класса (строки 5 и 11) столько раз, сколько понадобится. Функции-члены также могут быть объявлены в закрытой части, но обычно они открыты.
Для использования закрытых данных-членов TTime существует лишь один законный способ вызов открытых функций-членов класса. Непосредственный результат инкапсуляции данных и функций в классе: при изменении представления данных требуется переписать лишь функции-члены класса.
на рис. 2.2 стрелочками отмечены пути доступа к открытым и закрытым членам класса. Функции в классе имеют доступ друг другу, т.е. две функции класса могут вызывать одна другую.
Рис. 2.2. Классы ограничивают доступ к закрытым членам
В основной программе, поскольку данные-члены TTime закрыты в классе, больше невозможно присваивать значения непосредственно объекту класса. Например, оператор из CLASS1.CPP
ap.month = 7; // ???
вызвал бы сообщение об ошибке при компиляции, т.к. month закрыт в классе TTime и поэтому может непосредственно использоваться только членами этого класса.
В новой программе для присваивания значений объекту класса appointment потребуется вызвать функцию-член. Например, в строке 22 выполняется оператор, который устанавливает дату и время в appointment равными 14 июля 1996 года, 8:30:
appointment.SetTime(7,14,1996,8,30);
Аналогично, в строке 25 вызывается функция GetTime() для копирования значений данных-членов appointment в локальные переменные, объявленные в строке 20. Эти значения затем передается обратно SetTime() с увеличенным за 1 значением hour, что устанавливается в appointment следующий час.
Использование функций-членов
Большинство классов лучше объявлять в заголовочных файлах, которые затем могут включаться в многочисленные программные модули для совместного использования одинаковых классов.
В листинге 2.3 объявляется новый класс TTime с парочкой дополнительных функций-членов. Как и прежде, новый класс имеет несколько закрытых данных-членов.
Как и все заголовочные файлы, TIME1.H не программа, вы не можете скомпилировать и запустить ее на выполнение. Другие программные модули (листинги 2.4 и 2.5) включают этот заголовочный файл, делая объявления, содержащиеся в нем, доступными для операторов.
Применение заголовочных файлов не обязательный, но рекомендуемый способ улучшения организации частей программы.
Выполняет условное включение группы команд в код на этапе компиляции, если определена константа этапа компиляции.
Синтаксис
#IFDEF | #IFNDEF ConstantName
Commands
[#ELSE
Commands]
#ENDIF
Параметры #IFDEF Указывает, что на этапе компиляции следует включить заданную группу команд, если была определена константа этапа компиляции с именем ConstantName. Ниже описывается, каким образом группа команд включается в код на этапе компиляции при задании #IFDEF. Если константа ConstantName определена, на этапе компиляции включается группа команд, следующая за #IFDEF и предшествующая директиве #ELSE или #ENDIF(той из них, которая встретится раньше). Если константа ConstantName не определена и задана директива #ELSE, на этапе компиляции включается группа команд, следующая за #ELSE и предшествующая директиве #ENDIF. Если константа ConstantName не определена и директива #ELSE не задана, ни одна из команд, находящихся внутри структуры #IFDEF ... #ENDIF, не включается на этапе компиляции.
#IFNDEF Указывает, что на этапе компиляции следует включить заданную группу команд, если константа этапа компиляции с именем ConstantName не определена. Ниже описывается, каким образом группа команд включается в код на этапе компиляции при задании #IFNDEF. Если константа ConstantName не определена, на этапе компиляции включается группа команд, следующих за #IFNDEF и предшествующих директиве #ELSE или#ENDIF (той из них, которая встретится раньше). Если константа ConstantName определена и задана директива #ELSE, на этапе компиляции включается группа команд, следующих за #ELSE и предшествующих директиве #ENDIF. Если константа ConstantName определена и директива #ELSE не задана, ни одна из команд, находящихся внутри структуры #IFDEF ... #ENDIF, не включается на этапе компиляции. ConstantName Задает константу этапа компиляции, существование которой определяет необходимость включения группы команд на этапе компиляции. Константы этапа компиляции определяются с помощью директивы #DEFINE. Commands Задают группу команд, включаемых на этапе компиляции.
Комментарии Структуру #IFDEF | #IFNDEF ... #ENDIF можно вкладывать в другую структуру #IFDEF | #IFNDEF ... #ENDIF. Комментарии можно располагать в одной строке с директивами #IFDEF, #IFNDEF, #ELSE и #ENDIF. Комментарии игнорируются во время компиляции и выполнения программы.
Листинг 2.3 TIME.H (объявление класса TTIME в заголовочном файле)
1: //time.h-Объявление класса TTime
2:
//{$IfNDef Symbol} //Код выполняемый если
//Symbol определён ... {$Else} //Код выполняем
// если Symbol не определёный //{$EndIf}