Автор: Баженова И.Ю. Сухомлин В.А.
Теги: информационные технологии вычислительная техника обработка данных микропроцессоры программирование языки программирования учебное пособие искусство программирования
ISBN: 978-5-4497-3298-9
Год: 2024
И.Ю. Баженова, В.А. Сухомлин
Введение
в программирование
Учебное пособие
4-е издание (электронное)
Интернет-Университет
Информационных Технологий
www.intuit.ru
Ай Пи Ар Медиа
Москва
2024
УДК 004
ББК 32.97
Баженова, И. Ю.
Введение в программирование : учебное пособие / И.Ю. Баженова, В.А. Сухомлин. —
4-е изд. (эл.) — Москва : Национальный Открытый Университет «ИНТУИТ» ; Ай Пи Ар
Медиа, 2024. — 326 с. — Текст : электронный.
ISBN 978-5-4497-3298-9
В учебном пособии рассматриваются общие концепции разработки языков
программирования. Подробно изучаются основные конструкции языков программирования,
анализируются различные структуры данных, освещаются вопросы объектноориентированного программирования и сетевого программирования. Особое внимание
уделяется рассмотрению семантики языков программирования C++, С#, Java и Object Pascal.
Учебное пособие предназначено для студентов вузов, обучающихся по направлениям
подготовки, связанным с программированием и информационными технологиями.
Учебное электронное издание
Технический редактор А.А. Балакирева
Обложка С.С. Сизиумова, Я.А. Кирсанов
Подписано к использованию 16.07.2024.
© ООО «ИНТУИТ.РУ», 2005–2017
© Баженова И.Ю., Сухомлин В.А., 2005–2017
© Оформление электронного издания.
ООО Компания «Ай Пи Ар Медиа», 2024
О проекте
Интернет-Университет И н ф о р м а ц и о н н ы х Технологий — это первое
в России высшее учебное заведение, которое предоставляет возможность
получить дополнительное образование во Всемирной сети. Web-сайт у н и
верситета находится п о адресу www.intuit.ru.
М ы рады, что вы решили расширить свои знания в области к о м п ь ю
терных технологий. Современный м и р — это м и р компьютеров и и н ф о р
мации. Компьютерная индустрия — самый быстрорастущий сектор э к о н о
м и к и , и ее рост будет продолжаться еще долгое время. Во времена жесткой
конкуренции от уровня развития и н ф о р м а ц и о н н ы х технологий, достиже¬
н и й научной мысли и перспективных инженерных решений зависит успех
не только отдельных людей и компаний, н о и целых стран. Вы выбрали са¬
мое подходящее время для изучения компьютерных дисциплин. Профес¬
сионалы в области и н ф о р м а ц и о н н ы х технологий сейчас востребованы
везде: в науке, экономике, образовании, медицине и других областях, в го
сударственных и частных компаниях, в России и за рубежом. Анализ д а н
ных, прогнозы, организация связи, создание программного обеспечения,
построение моделей процессов — вот далеко н е полный список областей
применения знаний для компьютерных специалистов.
Обучение в университете ведется п о собственным учебным планам,
разработанным ведущими р о с с и й с к и м и специалистами на основе между¬
народных образовательных стандартов Computer Curricula 2001 Computer
Science. Изучать учебные курсы м о ж н о самостоятельно п о учебникам или
на сайте Интернет-Университета, задания выполняются только н а сайте.
Для обучения необходимо зарегистрироваться н а сайте университета.
Удостоверение об о к о н ч а н и и учебного курса или специальности выдает¬
ся п р и условии выполнения всех заданий к л е к ц и я м и успешной сдачи
итогового экзамена.
Книга, которую в ы держите в руках, — очередная в многотомной
серии «Основы и н ф о р м а ц и о н н ы х технологий», выпускаемой ИнтернетУ н и в е р с и т е т о м И н ф о р м а ц и о н н ы х Технологий. В э т о й серии будут
в ы п у щ е н ы учебники п о всем базовым областям з н а н и й , связанным с
компьютерными д и с ц и п л и н а м и .
Добро пожаловать в
Интернет-Университет Информационных Технологий!
Анатолий Шкред
anatoli@shkred.ru
Об а в т о р а х
Баженова Ирина Юрьевна
Кандидат физико-математических наук, доцент, старший научный с о
трудник лаборатории "Открытых информационных технологий" факульте
та Вычислительной математики и кибернетики Московского Государст
венного Университета им. М.В. Ломоносова, специалист в области постро
ения распределенных программных систем и технологий баз данных.
Баженова И . Ю . более 15 лет преподает на факультете В М и К М Г У
им. М.В. Ломоносова, ею разработан р я д учебных курсов п о и н ф о р м а ц и
о н н ы м технологиям, о н а является автором более десяти книг п о объект¬
но-ориентированному программированию и программированию прило¬
ж е н и й баз данных.
Сухомлин Владимир Александрович
Профессор, доктор технических наук, заведующий лабораторией от
крытых информационных технологий факультета В М и К МГУ им. М. В. Л о
моносова, действительный член Академии информатизации образования.
Более 30 лет преподает на факультете Вычислительной математики и
кибернетики ( В М и К ) . В настоящее время работает профессором и руко
водителем основанной и м научной лаборатории. Сухомлин В.А. являет
ся разработчиком и научным руководителем ряда магистерских п р о
грамм. И м также разработаны к о н ц е п ц и я и государственные стандарты
для нового научно-образовательного направления « И н ф о р м а ц и о н н ы е
Технологии», на основе которых министерством образования России в
2003 г. создано новое направление 511900 « И н ф о р м а ц и о н н ы е Техноло¬
гии». Имеет более 70 научных работ.
4
Содержание
Об авторах
4
Глава 1. Введение в программирование
13
Л е к ц и я 1. Развитие я з ы к о в программирования
13
Первые я з ы к и программирования
13
Области п р и м е н е н и я я з ы к о в программирования
15
Парадигмы программирования
15
Стандартизация я з ы к о в программирования
16
Среда проектирования
17
Л е к ц и я 2. Н Б Ф - н о т а ц и и
19
Модели трансляции
Трансляторы
Процесс трансляции
19
19
20
Формальные грамматики
НЕФ-грамматика
Расширенная НЕФ-нотация
23
23
24
Глава 2. Основные конструкции я з ы к о в программирования
25
Л е к ц и я 3. Управление последовательностью действий
25
Управляющие структуры
Определение последовательности
Операции
Операторы
действий в выражениях
...
25
25
27
29
Л е к ц и я 4. Управление подпрограммами
33
Простые подпрограммы
Определение и активация
33
33
подпрограмм
Последовательный вызов подпрограмм
34
Рекурсивный вызов подпрограмм
36
Л е к ц и я 5. Управление д а н н ы м и и параметрами подпрограмм
Управление д а н н ы м и
40
40
Блочно-структурированные я з ы к и программирования
41
Передача параметров
44
Ф у н к ц и и и процедуры
47
Глава 3. Структуры данных
48
Л е к ц и я 6. Простые т и п ы данных
48
П е р е м е н н ы е и константы
48
5
Объявление объектов данных
48
Типы данных
Типы данных языка С++
Преобразование типов в языке С++
Типы данных языка object PASCAL
Константы в языке OBJECT PASCAL
Типы данных языка JAVA
Типы данных языка С#
Представление
целочисленных
и вещественных типов данных
51
51
53
54
57
58
60
62
Л е к ц и я 7. Производные т и п ы данных языка С + + .
Массивы и указатели
66
Производные т и п ы
66
Массивы
Объявление массивов
Размещение массива в памяти
Элементы массива
Символьные массивы и строки
Указатели
Указатели на переменные
Константные указатели
Указатели на массивы
Указатели на указатели
Ссылки
Преобразование типа для указателей
Типы, определяемые в пространствах
имен
66
66
68
69
69
70
70
72
72
73
73
73
74
Л е к ц и я 8. Производные т и п ы данных языка С + + .
Структуры, объединения и перечисления
76
Структуры
Объявление структуры
Выделение памяти
Доступ к элементам структуры
Передача структур в качестве параметров
76
76
78
79
80
Объединения
81
Перечисления
82
Л е к ц и я 9. Структурированные т и п ы данных языка Object Pascal
Объявление производного типа
84
84
Множества
85
Массивы
87
6
Записи
90
Файлы
92
Глава .4. Объектно-ориентированное программирование
Л е к ц и я 10. С + + . Классы. Механизмы наследования.
Объектные т и п ы
Терминология объектно-ориентированного
программирования
94
94
94
Объектно-ориентированное программирование
на я з ы к е С + +
Структура приложения на языке С++
Объявление и реализация класса в языке С++
Конструкторы класса
Создание объекта
Вложенные классы
95
96
97
99
99
100
Объектные т и п ы
Преобразование объектных типов
Квалификация имен
100
101
102
Л е к ц и я 11. С + + . Методы - ч л е н ы класса.
Дружественные классы и члены класса
103
Методы — члены класса
Создание метода — члена класса
Методы с переменным числом параметров
Указатели на методы — члены класса и на функции
Встроенные функции
Перегрузка функций и методов
103
105
105
106
108
108
Дружественные члены класса
108
Дружественные классы
109
Л е к ц и я 12. С + + . Статические ч л е н ы класса. Виртуальные ф у н к ц и и
111
Статические члены класса
111
Виртуальные методы
113
Виртуальные
классы
115
Абстрактные классы
115
Ш а б л о н ы методов
115
Ш а б л о н ы классов
116
Работа с памятью
117
Л е к ц и я 13. Java. Механизмы наследования. Ссылочные т и п ы
данных. Интерфейсы. Вложенные классы
118
Механизмы наследования
118
Объявление класса
118
7
Раннее и позднее связывание
120
Объявление интерфейса
123
Вложенные классы
122
Абстрактные классы
123
Приведение ссылочных типов
123
Эквивалентность объектов
125
Пакеты классов J D K
126
Л е к ц и я 14. Java. Ч л е н ы класса. Статические переменые и методы . . . 127
Объявление переменных и методов класса
Объявление переменных
Определение методов
Передача параметров
Ссылка на текущий объект
Переопределение метода
Перегружаемые методы
127
127
128
131
131
132
133
Конструкторы
Создание объекта
133
134
Статические переменные
135
Л е к ц и я 15. С # . Классы и структуры. Объектные т и п ы
136
Объектно-ориентированное программирование
на я з ы к е С #
Управляемый код
Структура приложения на языке С#
Комментарии в программе на языке C#
Пространство имен
Пространство имен System
136
136
137
139
140
142
Создание классов
Объявление класса
Модификаторы доступа
Создание экземпляра класса
Явный вызов конструктора
Методы члены класса
143
143
144
147
148
148
Структуры
150
Л е к ц и я 16. C#. Механизмы наследования.
Абстрактные классы. И н т е р ф е й с ы
Механизмы наследования
Производные классы
Методы — члены класса
Виртуальные методы
153
153
153
154
156
8
Абстрактные классы
157
Интерфейсы
Определение интерфейса
Определение типа объекта
Приведение типа объекта к типу интерфейса
158
158
159
160
Вложенные классы
161
Л е к ц и я 17. C#. Индексаторы класса и атрибуты
163
Индексаторы
Создание индексаторов
Методы-аксессоры
Элементы индексатора
Индексаторы на базе многомерных массивов
163
163
165
165
166
Атрибуты
Назначение атрибута
Создание атрибута
Параметры атрибута
Позиционные и именованные параметры атрибута
Используемость атрибута
Доступ к атрибуту
Класс Type
Получение информации о методах
166
167
168
168
170
171
172
174
176
Л е к ц и я 18. C#. Отражения. Делегаты
178
Объявление делегата
Использование делегата для вызова методов
Применение делегатов как методов обратного вызова
178
178
179
П р и м е н е н и е неуправляемого кода
Небезопасный код
DLL-библиотеки
180
181
184
Глава 5. Системы проектирования
186
Л е к ц и я 19. Библиотека классов M F C среды проектирования
Visual Studio .NET. Диалоги
186
Создание приложений на С + + в Visual Studio . N E T
MFC-приложения
Приложения-диалоги
186
186
186
Классы диалогов библиотеки M F C
Класс CDialog
193
193
Стандартные диалоги
Класс CFileDialog
Класс CColorDialog
197
197
201
9
Л е к ц и я 20. Библиотека классов M F C среды проектирования
Visual Studio .NET. S D I и M D I приложения
202
Архитектура «документ-отображение»
Документы и отображения
Создание приложения с архитектурой
«документ-отображение»
Управление документом
202
202
Работа с отображениями
Классы отображений
Реализация интерфейса пользователя
Класс CView
Класс CFormView
Ш а б л о н ы документа
Класс CDocTemplate
Класс CSingleDocTemplate
Класс CMultiDocTemplate
205
205
206
208
209
209
209
210
211
Документы
Класс CDocument
Сериализация данных
211
211
211
Создание S D I - п р и л о ж е н и я
212
Л е к ц и я 21. Библиотека классов M F C
среды проектирования Visual Studio .NET.
Элементы управления
Элементы управления
Редактор ресурсов
Работа с элементами управления
Класс CEdit
Класс CStatic
Класс CButton
Класс CListBox
Класс CAnimateCtrl
Класс CComboBox
Класс CRichEditCtrl
Л е к ц и я 22. Библиотека классов M F C среды проектирования
Visual Studio .NET. Многостраничные диалоги
204
205
216
216
217
220
222
224
225
227
229
229
230
231
Создание многостраничных диалогов
Класс CPropertySheet
Класс PRopertyPage
231
233
234
С п и с к и изображений
Класс CImageList
235
235
10
Л е к ц и я 23. Библиотека классов . N E T Framework среды
проектирования Visual Studio .NET. Ф о р м ы Windows . . . . 237
Приложения—диалоги
Создание формы
Редактор формы
Класс Form
237
237
237
243
П р и м е н е н и е стандартных диалогов
246
Работа с м е н ю
247
Л е к ц и я 24. Библиотека классов V C L среды проектирования Delphi . 249
К о м п о н е н т ы Delphi
Объекты
Компоненты
249
249
249
Библиотека V C L
Иерархия классов
Класс TObject
Класс TComponent
Класс TControl
Класс TWinControl
Класс TApplication
Класс TScreen
Класс TForm
Класс TMainMenu
Класс TMenuItem
Класс TPopupMenu
250
250
250
251
252
253
253
254
254
256
257
260
Л е к ц и я 25. Библиотека классов V C L среды
проектирования Delphi. П р и л о ж е н и я и диалоги
Создание приложений
Проекты
Создание MDI-приложения
Создание DLL-библиотеки
Статическое и динамическое
подключения
DLL-библиотеки
Создание и освобождение ф о р м
Главная форма приложения
Использование модальной формы
Использование немодальной формы
Классы стандартных диалогов
268
272
270
270
271
271
Л е к ц и я 26. Библиотека классов J D K . Основы построения
интерфейса пользователя на я з ы к е Java. События
273
События
261
261
261
261
266
273
11
Типы событий
Блоки прослушивания
Классы—адаптеры
Блоки прослушивания
пакета JDK
Методы — обработчики событий
События окна
События от клавиатуры
События действия
Л е к ц и я 27. Библиотека классов J D K . Основы построения
интерфейса пользователя на я з ы к е Java.
К о м п о н о в к и и элементы управления
273
273
274
276
280
280
281
284
286
Менеджеры к о м п о н о в о к
Применение компоновок
286
286
Классы к о м п о н о в о к
Класс BorderLayout
Класс CardLayout
Класс FlowLayout
Класс GridLayout
Класс GridBagLayout
288
288
289
290
291
292
К о м п о н е н т ы графического интерфейса пользователя
Панели
Кнопки
Текстовые компоненты
Списки
293
293
297
302
308
Глава 6. Программирование для Интернет
Л е к ц и я 28. Серверные приложения
310
310
Взаимодействие по протоколу T C P / I P
310
Создание серверных приложений на С + + в среде
проектирования VisualStudio . N E T
CGI и ISAPI приложения
HTTP-запросы
Создание ISAPI-приложения
Выполнение ISAPI-приложения
310
310
311
311
317
Создание приложений, выполняемых
на WEB-сервере, в среде проектирования D E L P H I
Создание CGI-приложения
Разбор параметров
Применение Cookies
Создание Web-форм В VisualStudio . N E T
318
319
321
321
322
12
Лекция 1
Развитие языков программирования
Глава 1. Введение в программирование
Лекция 1. Развитие языков программирования
Первые языки программирования
В пятидесятые годы X X века с появлением компьютеров на электрон
ных лампах началось бурное развитие языков программирования. К о м п ь
ютеры, стоившие в то время значительно дороже, чем разработка любой
программы, требовали высокоэффективного кода. Такой код разрабаты
вался вручную на я з ы к е Ассемблер. В середине 1950-х годов под руковод
ством Джона Бэкуса для ф и р м ы I B M был разработан алгоритмический
я з ы к программирования F O R T R A N . Несмотря на то, что уже существова
ли разработки языков, выполняющие преобразование арифметических
в ы р а ж е н и й в м а ш и н н ы й код, создание я з ы к а F O R T R A N (FORmula
TRANslator), предоставляющего возможность записи алгоритма вычисле¬
н и й с использованием условных операторов и операторов ввода/вывода,
стало точкой отсчета эры алгоритмических языков программирования.
К я з ы к у F O R T R A N предъявлялись требования создания в ы с о к о э ф
фективного кода. Поэтому многие конструкции я з ы к а первоначально
разрабатывались с учетом архитектуры I B M 407. Успех разработки этого
я з ы к а привел к тому, что производители других вычислительных систем
стали создавать свои версии трансляторов. С целью некоторой возмож
н о й на тот момент у н и ф и к а ц и и я з ы к а я з ы к F O R T R A N IV, разработанный
в 1966 году, стал первым стандартом, именуемым F O R T R A N 66.
К а к альтернатива я з ы к у F O R T R A N , первоначально ориентирован
ному на архитектуру I B M , под руководством Питера Наура в конце 1950-х
годов был разработан я з ы к A L G O L (ALGOrithmic Language). Основной
целью, преследуемой разработчиками этого я з ы к а , была независимость
от конкретной архитектуры вычислительной системы. К р о м е того, созда¬
тели я з ы к а A L G O L стремились разработать я з ы к , удобный для описания
алгоритмов и п р и м е н я ю щ и й систему обозначений, близкую к той, что
принята в математике.
Я з ы к и F O R T R A N и A L G O L были первыми я з ы к а м и , ориентирован¬
н ы м и на программирование вычислений.
Я з ы к P L / I , первые версии которого появились в начале 1960-х го
дов, был первоначально ориентирован на I B M 360 и расширял возможно
сти я з ы к а F O R T R A N некоторыми средствами я з ы к а C O B O L , разработан
ного в те ж е годы. Несмотря на определенную популярность языка P L / I
13
Курс
Введение в программирование
у программистов, работавших на компьютерах I B M и м а ш и н а х серии Е С ,
в настоящее время о н представляет чисто теоретический интерес.
В к о н ц е 1060-х годов под руководством Найарда и Дала был разрабо
тан я з ы к Simula-67, использующий к о н ц е п ц и ю пользовательских типов
данных. Фактически это первый я з ы к , п р и м е н я ю щ и й понятие классов.
В середине 1970-х годов Вирт предложил я з ы к Pascal, который сразу
стал ш и р о к о использоваться. В это ж е время по инициативе Министерст
ва обороны С Ш А началась работа по созданию я з ы к а высокого уровня,
получившего название Ada — в честь Ады Лавлейс, программистки и д о
чери лорда Байрона. Создание языка началось с определения требований
и выработки с п е ц и ф и к а ц и й . Над проектом работали четыре независимые
группы, но все они использовали как основу я з ы к Pascal. В начале 1980-х
годов был разработан первый п р о м ы ш л е н н ы й компилятор языка Ada.
Универсальный я з ы к программирования С был разработан в середи
не 1970-х годов Д е н и с о м Ритчи и К е н о м Томпсоном. Этот я з ы к стал п о
пулярным я з ы к о м системного программирования и в свое время исполь
зовался для н а п и с а н и я ядра операционной системы U N I X . Стандарт я з ы
ка С начал разрабатываться рабочей группой института стандартов A N S I
в 1982 году. Международный стандарт я з ы к а С принят в 1990 году. Я з ы к С
лег в основу разработки я з ы к о в программирования C++ и Java.
Наряду с алгоритмическими я з ы к а м и параллельно развивались и
я з ы к и , предназначенные для обработки деловой и н ф о р м а ц и и , а также
я з ы к и искусственного интеллекта. К первым относится я з ы к C O B O L
(COmmon Business Oriented Language), а ко вторым — я з ы к и L I S P (LISt
Processing) и Prolog. Я з ы к LISP, разработанный в 1960-х годах под руко¬
водством Дж. Маккарти, был первым ф у н к ц и о н а л ь н ы м я з ы к о м обработ¬
ки списков, который нашел ш и р о к о е п р и м е н е н и е в теории игр.
С появлением персональных компьютеров языки стали составными ча
стями интегрированных сред разработки. Появились языки, применяемые в
различных офисных программах, например V B A (Visual Basic for Application).
В 1990-х годах с распространением сети Интернет расширяется воз
можность распределенной обработки данных, что отражается и на разви
тии я з ы к о в программирования. Появляются я з ы к и , ориентированные на
создание серверных приложений, такие как Java, Perl и PHP, я з ы к и о п и
сания документов — H T M L и X M L . Традиционные я з ы к и программиро
вания С + + и Pascal также претерпевают изменения: под я з ы к о м програм
мирования начинает пониматься не только функциональность самого
языка, а также библиотеки классов, предоставляемые средой программи
рования. Акцент со с п е ц и ф и к а ц и и самих я з ы к о в программирования п е
реносится на стандартизацию механизмов взаимодействия распределен
ных приложений. Появляются новые технологии — C O M и C O R B A , спе¬
ц и ф и ц и р у ю щ и е взаимодействие распределенных объектов.
14
Лекция 1
Развитие языков программирования
Области применения языков программирования
В настоящее время я з ы к и программирования применяются в самых
различных областях человеческой деятельности, таких как:
• научные вычисления (языки C++, F O R T R A N , Java);
• системное программирование (языки C++, Java);
• обработка и н ф о р м а ц и и (языки C++, C O B O L , Java);
• искусственный интеллект (LISP, Prolog);
• издательская деятельность (Postscript, TeX);
• удаленная обработка и н ф о р м а ц и и (Perl, PHP, Java, C++);
• описание документов ( H T M L , X M L ) .
С течением времени одни я з ы к и развивались, приобретали новые
черты и остались востребованы, другие утратили свою актуальность и се¬
годня представляют в лучшем случае чисто теоретический интерес. В зна
чительной степени это связано с такими факторами, как:
• наличие среды программирования, поддерживающей разработку
приложений на конкретном я з ы к е программирования;
• удобство сопровождения и тестирования программ;
• стоимость разработки с п р и м е н е н и е м конкретного я з ы к а програм
мирования;
• четкость и ортогональность конструкций я з ы к а ;
• п р и м е н е н и е объектно-ориентированного подхода.
Парадигмы программирования
Синтаксис я з ы к а описывает систему правил н а п и с а н и я различных
я з ы к о в ы х конструкций, а семантика я з ы к а программирования определя
ет смысл этих конструкций. Синтаксис я з ы к а программирования может
быть описан с п о м о щ ь ю Н Б Ф - н о т а ц и й .
Семантика языка взаимосвязана с используемой вычислительной м о
делью. В настоящее время языки программирования в зависимости от при
меняемой вычислительной модели делятся на четыре основные группы:
• Процедурные языки, которые представляют собой последователь
ность выполняемых операторов. Если рассматривать состояние П К
как состояние ячеек памяти, то процедурный я з ы к — это последова
тельность операторов, и з м е н я ю щ и х значение одной или нескольких
ячеек. К процедурным я з ы к а м относятся F O R T R A N , C , Ada, Pascal,
Smalltalk и некоторые другие. Процедурные я з ы к и иногда также на
зываются императивными я з ы к а м и . Код программы на процедур
ном я з ы к е может быть записан следующим образом:
o p e r a t o r l ; operator2;
operator3.
15
Курс
Введение в программирование
• Аппликативные языки, в основу которых положен ф у н к ц и о н а л ь н ы й
подход. Я з ы к рассматривается с точки зрения нахождения ф у н к ц и и ,
необходимой для перевода памяти П К из одного состояния в другое.
Программа представляет собой набор ф у н к ц и й , применяемых к н а
чальным д а н н ы м , п о з в о л я ю щ и й получить требуемый результат. К
аппликативным я з ы к а м относится я з ы к LISP. Код программы на а п пликативном я з ы к е может быть записан следующим образом:
function1(function2(function3(beginning_date))).
• Языки системы правил, называемые также я з ы к а м и логического п р о
граммирования, основываются на определении набора правил, при
выполнении которых возможно в ы п о л н е н и е определенных дейст¬
вий. Правила могут задаваться в виде утверждений и в виде таблиц
решений. К я з ы к а м логического программирования относится я з ы к
Prolog.
Код программы на я з ы к е системы правил может быть записан следу¬
ю щ и м образом:
i f c o n d i n i o n l then o p e r a t o r l ;
i f condinion2 then operator2;
i f condinion3 then operator3.
• Объектно-ориентированные
языки, о с н о в а н н ы е на построении объе¬
ктов как набора данных и операций над н и м и . Объектно-ориентиро¬
в а н н ы е я з ы к и объединяют и расширяют возможности, присущие
процедурным и аппликативным я з ы к а м . К объектно-ориентирован
н ы м я з ы к а м относятся C++, Object Pascal, Java.
В настоящий момент наибольшее распространение получили я з ы к и ,
основанные на объектно-ориентированной модели. О н и , реализуя п р о
цедурную модель построения языка, поддерживают аппликативность
конструкций, позволяя представлять блок-схему в ы п о л н е н и я структури¬
рованной программы как некоторый набор аппликативных ф у н к ц и й .
Стандартизация языков программирования
К о н ц е п ц и я я з ы к а программирования неотрывно связана с его реа
лизацией. Для того чтобы к о м п и л я ц и я одной и той ж е программы различ
н ы м и компиляторами всегда давала одинаковый результат, разрабатыва
ются стандарты я з ы к о в программирования. Существует ряд организаций,
целенаправленно занимающихся вопросами стандартизации. Это Амери¬
к а н с к и й национальный институт стандартов A N S I (American National
16
Лекция 1
Развитие языков программирования
Standards Institute), Институт инженеров п о электротехнике и электрони¬
ке I E E E (Institute of Electrical and Electronic Engineers), Организация меж
дународных стандартов ISO (International Standards Organization).
К а к правило, п р и создании я з ы к а выпускается частный стандарт,
определяемый разработчиками языка. Если я з ы к получает ш и р о к о е рас
пространение, то со временем появляются различные версии компилято¬
ров, которые н е точно следуют частному стандарту. В большинстве случа¬
ев идет р а с ш и р е н и е первоначально зафиксированных возможностей я з ы
ка. Д л я приведения наиболее популярных реализаций языка в соответст
вие друг с другом разрабатывается согласительный стандарт. Очень важ
н ы м фактором стандартизации языка программирования является свое
временность появления стандарта — д о широкого распространения я з ы к а
и создания множества несовместимых реализаций. В процессе развития
я з ы к а могут появляться новые стандарты, отражающие современные н о
вовведения. Так, я з ы к F O R T R A N первоначально был стандартизирован в
1966 году. В результате был издан стандарт F O R T R A N 66. Далее этот стан
дарт несколько раз пересматривался (в 1977 году был выпущен F O R T R A N
77, затем появился и F O R T R A N 90).
Я з ы к Java, ставший в последнее время весьма распространенным,
постепенно был значительно расширен и модифицирован: новая специ
ф и к а ц и я получила название Java 2.
В процессе развития языка некоторые его конструкции и функции
устаревают. Однако с целью обратной совместимости новые версии долж¬
н ы поддерживать и все устаревающие возможности. Это ведет к «разбуха
нию» компиляторов. В последнее время в реализациях введено понятие
нерекомендуемой и устаревшей возможности. В первом случае следую¬
щ и й стандарт еще будет поддерживать нерекомендуемую возможность, н о
может перевести ее в категорию устаревшей. Во втором случае стандарт
может исключить поддержку возможности, объявленной ранее как уста
ревшая. Введение нерекомендуемых и устаревших возможностей предос
тавляет разработчикам временной интервал, в течение которого о н и могут
модифицировать код в соответствии с новыми требованиями стандарта.
Среда проектирования
С развитием я з ы к о в программирования совершенствовались и сред¬
ства разработки программ — от режима командной строки до интегриро¬
ванной среды проектирования. Такая среда предоставляет удобный гра¬
ф и ч е с к и й интерфейс разработки и большой спектр сервисов, включаю¬
щих управление версиями хранимых данных, утилиты просмотра и упра
вления и н ф о р м а ц и е й , библиотеки классов, мастера создания шаблонов
приложений и т.п.
17
Курс
Введение в программирование
К о м п и л я т о р я з ы к а п р о г р а м м и р о в а н и я выступает к а к составная
часть среды проектирования. Сама программа наряду с конструкциями,
предусмотренными стандартом, к а к правило, использует библиотечные
ф у н к ц и и и классы, предоставляемые средой проектирования. Так, интег
р и р о в а н н а я среда разработки VisualStudio.NET содержит библиотеку
классов M F C (Microsoft Foundation Classes), значительно упрощающую
процесс разработки приложений, использующих о к о н н ы й интерфейс.
Интегрированная среда проектирования VisualStudio.NET позволяет
создавать и компилировать приложения на языках C++, C#, Visual Basic
и Visual J#. Для разработки приложений на я з ы к е С + + предназначается
также среда CBuilder.
Для проектирования приложений на я з ы к е Object Pascal использует
ся и н т е г р и р о в а н н а я среда п р о е к т и р о в а н и я Borland Developer Studio
(Delphi).
Наиболее удобной средой разработки программ на я з ы к е Java я в л я
ется интегрированная среда проектирования JBuilder.
18
НБФ-нотации
Лекция 2
Лекция 2. НБФ-нотации
Модели трансляции
Трансляторы
Программа, написанная на языке высокого уровня, перед ис
п о л н е н и е м должна быть преобразована в программу на "машинном
языке". Такой процесс называется трансляцией, или компиляцией.
П о типу выходных д а н н ы х различают два основных вида трансля¬
торов:
• к о м п и л и р у ю щ и е о к о н ч а т е л ь н ы й в ы п о л н и м ы й код;
• компилирующие интерпретируемый код, для выполнения которо
го требуется д о п о л н и т е л ь н о е п р о г р а м м н о е обеспечение.
Окончательным в ы п о л н и м ы м кодом являются приложения, реали
зованные как EXE-файлы, DLL-библиотеки, C O M - к о м п о н е н т ы . К и н
терпретируемому коду м о ж н о отнести байт-код JAVA-программ, выпол
н я е м ы й посредством виртуальной м а ш и н ы J V M .
Я з ы к и , ф о р м и р у ю щ и е окончательный в ы п о л н и м ы й код, называют¬
ся компилируемыми я з ы к а м и . К н и м относятся я з ы к и С, C++, F O T R A N ,
Pascal. Я з ы к и , реализующие интерпретируемый код, называются интер
претируемыми я з ы к а м и . К таким я з ы к а м относятся я з ы к Java, LISP, Perl,
Prolog.
В большинстве случаев код, получаемый в результате процесса
трансляции, формируется из нескольких программных модулей. П р о
граммным модулем называется определенным образом о ф о р м л е н н ы й
код на я з ы к е высокого уровня. Процесс трансляции в этом случае может
выполняться как единое целое — к о м п и л я ц и я и редактирование связей,
или как два отдельных этапа — сначала к о м п и л я ц и я объектных модулей,
а затем вызов редактора связей, создающего окончательный код. Послед
н и й подход более удобен для разработки программ. О н реализован в
трансляторах я з ы к о в С и С + + .
Объектный код, создаваемый компилятором, представляет собой
область данных и область м а ш и н н ы х команд, имеющих адреса, которые в
дальнейшем "согласуются" редактором связи (иногда называемым загруз
ч и к о м ) . Редактор связи размещает в едином адресном пространстве все
по отдельности откомпилированные объектные модули и статически
подключаемые библиотеки.
Будем называть в ы п о л н и м о й ф о р м о й программы код, получаемый в
результате трансляции исходной программы.
19
Курс
Введение в программирование
Процесс трансляции
Программу, н а п и с а н н у ю на я з ы к е п р о г р а м м и р о в а н и я высокого
уровня, называют исходной программой, а каждую самостоятельную п р о
граммную единицу, образующую данную программу, — программным м о
дулем. Для преобразования исходной программы в ее выполняемую ф о р
му ( в ы п о л н и м ы й файл) транслятор выполняет некоторую последователь
ность действий. Эта последовательность зависит как от я з ы к а программи
р о в а н и я , так и от конкретной реализации самого транслятора. В ходе
трансляции важно не просто откомпилировать программу, а получить при
этом достаточно э ф ф е к т и в н ы й код.
В процессе трансляции выполняется анализ исходной программы, а
затем — синтез выполнимой ф о р м ы д а н н о й программы. В зависимости
от числа просмотров исходной программы, выполняемых компилятором,
трансляторы разделяются на однопроходные, двухпроходные и трансля¬
торы, использующие более двух проходов.
К достоинствам однопроходного компилятора м о ж н о отнести высо
кую скорость к о м п и л я ц и и , а к недостаткам — получение, как правило, не
самого эффективного кода.
Ш и р о к о е распространение получили двухпроходные компиляторы.
О н и позволяют при первом проходе выполнить анализ программы и по¬
строить и н ф о р м а ц и о н н ы е таблицы, используемые при втором проходе
для ф о р м и р о в а н и я объектного кода.
На рис. 2.1 представлены основные этапы, в ы п о л н я е м ы е в процессе
трансляции исходной программы.
Фаза анализа программы состоит из:
• лексического анализа;
• синтаксического анализа;
• семантического анализа.
П р и анализе исходной программы транслятор последовательно про¬
сматривает текст программы, представимой как набор символов, выпол¬
н я я разбор структуры программы.
На этапе лексического анализа выполняется выделение основных со
ставляющих программы — лексем. Лексемами являются ключевые слова,
идентификаторы, символы операций, комментарии, пробелы и раздели¬
тели. Лексический анализатор не только выделяет лексемы, но и опреде
ляет тип каждой лексемы. П р и этом на этапе лексического анализа соста
вляется таблица символов, в которой каждому идентификатору сопостав
лен свой адрес. Это позволяет при дальнейшем анализе вместо конкретно
го значения (строки символов) использовать его адрес в таблице символов.
Процесс выделения лексем достаточно трудоемок и требует п р и м е
н е н и я сложных контекстно-зависимых алгоритмов.
20
Лекция 2
НБФ-нотации
Рис. 2.1. Основные этапы трансляции программы
21
Курс
Введение в программирование
На этапе синтаксического анализа выполняется разбор полученных
лексем с целью получения семантически понятных синтаксических еди
н и ц , которые затем обрабатываются семантическим анализатором. Так,
синтаксическими единицами выступают: выражение, объявление, опера
тор языка программирования, вызов ф у н к ц и и .
На этапе семантического анализа выполняется обработка синтакси¬
ческих единиц и создание промежуточного кода. В зависимости от нали¬
ч и я или отсутствия фазы оптимизации результатом семантического ана
лиза может быть оптимизируемый далее промежуточный код или готовый
объектный модуль.
К наиболее о б щ и м задачам, р е ш а е м ы м семантическим анализато¬
р о м , относятся:
• обнаружение о ш и б о к времени к о м п и л я ц и и ;
• заполнение таблицы символов, созданной на этапе лексического
анализа, к о н к р е т н ы м и значениями, определяющими дополнитель¬
ную и н ф о р м а ц и ю о каждом элементе таблицы;
• замена макросов их определениями;
• выполнение директив времени к о м п и л я ц и и .
Макросом называется некоторый предварительно определенный
код, который на этапе к о м п и л я ц и и вставляется в программу во всех мес
тах указания вызова данного макроса.
На фазе синтеза программы производится:
• генерация кода;
• редактирование связей.
Процесс генерации кода состоит из преобразования промежуточно¬
го кода (или оптимизированного кода) в объектный код. П р и этом в зави¬
симости от я з ы к а программирования получаемый объектный код может
быть представлен в в ы п о л н и м о й ф о р м е или как объектный модуль, под¬
лежащий дальнейшей обработке редактором связей.
Так, процесс генерации кода является неотъемлемой частью ф а з ы
синтеза программы, а необходимость выполнения редактора связей зави
сит от конкретного я з ы к а программирования. Следует учесть, что на пра
ктике термин «генерация кода» часто применяют ко всем действиям фа¬
зы синтеза программы, ведущим к получению в ы п о л н и м о й ф о р м ы про¬
граммы.
Редактор связей приводит в соответствие адреса фрагментов кода,
расположенных в отдельных объектных модулях: определяются адреса
вызываемых внешних ф у н к ц и й , адреса внешних переменных, адреса
ф у н к ц и й и методов каждого модуля. Для редактирования адресов редак
тор связей использует специальные, создаваемые на этапе трансляции,
таблицы загрузчика. После обработки объектных модулей редактором
связей генерируется выполнимая форма программы.
22
НБФ-нотации
Лекция 2
Формальные грамматики
НБФ-грамматика
Грамматикой называется формальное описание синтаксиса я з ы к а
программирования.
Грамматика определяется набором правил (называемых иногда пра
вилами подстановки), определяющих ф о р м и р о в а н и е из лексем достовер¬
ных программ.
Формальная грамматика использует строгую систему обозначений.
Существуют различные т и п ы грамматик. Н Б Ф грамматика является к о н
текстно-свободной грамматикой. Эта грамматика использует Н Б Ф - н о т а ц и и , предложенные Д ж о н о м Бэкусом в к о н ц е 1950-х годов для описания
синтаксиса я з ы к а A L G O L .
Простая Н Б Ф - н о т а ц и я позволяет описывать все достоверные конст
рукции я з ы к а программирования, используя следующие символы:
• символ : : = имеет значение "определяется как" и предшествует указа¬
н и ю всех допустимых значений описываемой синтаксической еди¬
ницы;
• символ | имеет значение "или" и используется для перечисления аль¬
тернативных вариантов;
• пара символов < > ограничивает имя синтаксической единицы, называ
емой также нетерминальным символом или синтаксической категорией.
Значения, указываемые вне скобок < >, называются терминальными
символами.
Н Б Ф - г р а м м а т и к а состоит из набора правил (называемых иногда ме
талингвистическими формулами или продукциями), записываемых при
помощи НБФ-нотации.
Например:
<цифра>:= 0|1|2|3|4|5|6|7|8|9
«целочисленное значение> ::=
цифра | цифра < целочисленное значение>
В д а н н о м примере символы 0, 1, 2, 3 и т.д. являются терминальными
символами.
П р и построении грамматики, описывающей я з ы к программирова
н и я , выделяется начальный нетерминальный символ, определяющий
конструкцию "программа".
Существуют порождающие и распознающие грамматики. Порожда¬
ю щ а я грамматика генерирует множество цепочек терминальных с и м в о
лов из начального символа, а распознающая грамматика используется для
23
Курс
Введение в программирование
построения по цепочке символов дерева грамматического разбора, веду¬
щего к начальному символу.
М о ж н о сказать, что грамматика состоит из множества терминаль¬
ных и нетерминальных символов, начального нетерминального символа
и набора правил. В 1959 году Ноар Хомский предложил следующую клас¬
с и ф и к а ц и ю грамматик:
• регулярные грамматики, используемые для построения лексических
анализаторов;
• контекстно-свободные грамматики, используемые для построения
дерева грамматического разбора. К этому типу относятся Н Б Ф грамматики;
• контекстно-зависимые грамматики, представляемые набором пра
вил типа x->y, в которых х может быть любой цепочкой нетерми
нальных символов, а y — цепочкой терминальных и нетерминальных
символов. Этот тип грамматик намного сложнее контекстно-сво¬
бодных грамматик и не имеет столь широкого п р и м е н е н и я при м о
делировании я з ы к о в программирования;
• грамматики с фразовой структурой, реализуемые набором правил
типа x->y, в которых х может быть любой цепочкой нетерминальных
символов, а y — цепочкой терминальных и нетерминальных симво¬
лов (при этом нет никаких ограничений на длину получаемых цепо¬
ч е к символов). Большинство таких грамматик являются неразреши¬
м ы м и и не имеют практического интереса.
Расширенная НБФ-нотация
П р и о п и с а н и и правил Н Б Ф - г р а м м а т и к и с п р и м е н е н и е м стандарт¬
ной Н Б Ф нотации синтаксические конструкции, и м е ю щ и е необязатель
н ы е или альтернативные элементы, выглядят при всей их простоте доста
точно громоздко. Расширенная Н Б Ф - н о т а ц и я вводит ряд дополнитель
ных элементов, позволяющих значительно улучшить наглядность пред
ставления правил Н Б Ф - г р а м м а т и к и .
Р а с ш и р е н н а я Н Б Ф - н о т а ц и я вводит следующие дополнительные
элементы:
• необязательные элементы указываются заключенными в квадратные
скобки;
• альтернативные элементы, указываемые через символ вертикальной
черты, также могут являться необязательными элементами, заклю¬
чаемыми в квадратные скобки;
• последовательность нескольких однотипных элементов обозначает¬
ся заключением элемента в фигурные скобки, за которыми указыва
ется символ «звездочка» ({<целое>}*).
24
Лекция 3
Управление последовательностью действий
Глава 2. Основные конструкции языков
программирования
Л е к ц и я 3. У п р а в л е н и е п о с л е д о в а т е л ь н о с т ь ю
действий
Управляющие структуры
Управление последовательностью действий в языках программиро
вания может быть представлено некоторой управляющей структурой. Та
кая структура называется н е я в н ы м управлением в том случае, если после
довательность действий определяется естественным образом (например,
в ы п о л н е н и е программы идет с первого оператора и т.д.). Управляющая
структура представляет собой я в н о е управление в том случае, если для и з
менения порядка в ы п о л н е н и я действий используются какие-либо опера
торы или и н ы е синтаксические конструкции. О с н о в н ы м и управляющи
ми структурами принято считать:
• операторы;
• выражения;
• подпрограммы.
В языках логического программирования управляющие структуры
могут представляться несколько иначе. Так, в я з ы к е Prolog модель управ
л е н и я последовательностью действий вместо операторов использует та¬
к и е категории, как факты, правила и запросы.
Определение последовательности действий
в выражениях
Выражение состоит из операций, операндов и ф у н к ц и й (функции
м о ж н о рассматривать как особый тип операции). Операндами могут вы¬
ступать переменные и константы. Операторы, определяющие операции,
могут быть у н а р н ы м и и бинарными.
Унарный оператор действует только на один операнд, а бинарный
оператор — на два операнда.
Синтаксис выражения можно представить в виде дерева: вершиной де
рева является последняя выполняемая операция, узлы описывают промежу
точные операции, а листья указывают данные (переменные или константы).
На рисунке 3.1 показано древовидное представление вычисления
в ы р а ж е н и я (x*y) - x * ( - (x**2)+(y - 0,3)).
25
Курс
Введение в программирование
Рис. 3.1. Древовидное представление выражения
Для представления выражения в л и н е й н о й форме применяются сле
дующие ф о р м ы записи:
• п р е ф и к с н а я запись;
• постфиксная запись;
• и н ф и к с н а я запись.
В п р е ф и к с н о й записи, называемой также польской п р е ф и к с н о й за
писью, сначала записывается символ операции, а затем по порядку слева
направо записываются операнды. Так, выражение (z + 2)*(x + y) в пре
ф и к с н о й записи будет иметь следующий вид: * + z 2 + x y. Польская пре
ф и к с н а я запись не содержит скобок и позволяет однозначно определять
порядок вычисления выражения.
Я з ы к L I S P для представления выражений использует п р е ф и к с н ы й
тип записи, называемый кембриджской польской записью. Такая запись
в отличие от польской записи содержит скобки, ограничивающие опе¬
ранды, на которые действует операция. Таким образом, в кембриджской
польской записи выражение представляет собой множество вложенных
подвыражений, ограниченных скобками.
Например: * (+ (z 2) + (x y ) ) .
В п о с т ф и к с н о й записи, называемой также обратной польской запи¬
сью или суффиксной записью, символ операции записывается после опе
рандов. Выражение (z + 2)*(x + y) в п о с т ф и к с н о й записи будет иметь
следующий вид: z 2 + x y + * .
Третьим типом записи выражений является инфиксная запись, ис
пользуемая для представления выражений как в математике, так и в языках
26
Лекция 3
Управление последовательностью действий
программирования. И н ф и к с н а я запись — это стандартный способ записи
выражений, при котором символ операции указывается между операндами.
Однако инфиксная запись не позволяет представлять унарные операции.
Наиболее простым представлением выражения с точки зрения п р о
цесса трансляции является постфиксная запись. Однако п р е ф и к с н а я за¬
пись более удобно обеспечивает обработку ф у н к ц и й . К р о м е того, пре¬
ф и к с н а я запись позволяет вычислить выражение за один просмотр транс
лятора, но существенным недостатком при этом является то, что для ка
ждой операции требуется предварительно знать число обрабатываемых
ею операндов (унарная, бинарная, ф у н к ц и я ) .
Операции
П р и вычислении выражений учитывается приоритет операций: сна
чала выполняются операции с более высоким приоритетом.
Вычисление выражений, имеющих операции с одинаковым п р и о р и
тетом, производится в соответствии с правилом сочетательности, которое
определяет порядок в ы п о л н е н и я таких операций. В я з ы к е С сочетатель
ность операций применяется к а к слева направо, так и справа налево (как
и при вычислении возведения в степень). П о р я д о к вычисления справа
налево означает, что выражение x** 2**4 трактуется как x**(2 **4).
В следующей таблице приведены в убывающем порядке уровни п р и
оритета операций я з ы к а С.
Уровни приоритета
Операции
Порядок выполнения
операций
Скобки
И н д е к с ы , вызов ф у н к ц и й
( ), [ ]
x [ i ] , fun()
слева направо
П о с т ф и к с н ы й инкремент
и декремент
++,
--
слева направо
П р е ф и к с н ы й инкремент
и декремент
Унарный минус
Поразрядное отрицание
(NOT)
Размер объекта
Логическое отрицание
Получение адреса
и разыменование
++,
--
справа налево
sizeof
!
&, *
Я в н о е приведение типа
(any_type)
Умножение, деление,
деление по модулю
*, / , %
слева направо
слева направо
27
Курс
Введение в программирование
Уровни приоритета
Операции
Порядок выполнения
операций
Сложение, вычитание
+, -
слева направо
Сдвиг влево, сдвиг вправо
<<, >>
слева направо
Сравнение (меньше,
больше, меньше или
равно, больше и л и равно)
слева направо
Сравнение (тождественное
равенство, неравенство)
==
Поразрядное логическое И
&
!
=
слева направо
слева направо
Поразрядное
исключающее И Л И
(XOR)
слева направо
Поразрядное
логическое И Л И
I
слева направо
Логическое И ( A N D )
&&
слева направо
Логическое И Л И (OR)
I I
слева направо
Условная операция
?
справа налево
Операция перед
присваиванием
= , +=, -=, *=, /=,
%=, <<=, >>=,
:
справа налево
&=, "=, 1=
Операции A N D , O R , N O T и X O R относятся к логическим операци
ям. Следующая таблица показывает результаты п р и м е н е н и я логических
операций.
x
y
x && y
(x AND y)
x || y
(x OR y)
!x
(NOT x)
(x XOR y)
0 (false)
0 (false)
0
0
1
0
0 (false)
1(true)
0
1
1
1
1 (true)
0(false)
0
1
0
1
1 (true)
1(true)
1
1
0
0
Единственной операцией, и м е ю щ е й три операнда, является опера
ц и я «условие» (называемая также условной операцией).
Условная операция имеет следующий формальный синтаксис:
( e x p r _ l o g ) ? expr1:expr2.
28
Лекция 3
Управление последовательностью действий
Если выражение expr l o g принимает значение true, то условная о п е
р а ц и я возвращает значение expr1, а если f a l s e , то значение expr2.
Например: x = (y > z ) ? 1:0;
// x примет значение 1, если y > z.
Операции сдвига целочисленного значения выполняют сдвиг
всех битов операнда, указанного слева, н а число п о з и ц и й , заданных
операндом, указанным справа, а вместо сдвинутых битов записыва
ю т с я н у л и . О п е р а ц и и с д в и г а и м е ю т с л е д у ю щ и й ф о р м а л ь н ы й син¬
таксис:
value<<count_of_posltlon
value>>count_of_posltlon
Н а п р и м е р , выражение 9<<2 вычисляется следующим образом: ч и с л о
9 и м е е т в д в о и ч н о м п р е д с т а в л е н и и з н а ч е н и е 001001 ( 1 1 ) и при сдви
ге его на два разряда влево получается значение 100100 (44 ).
Операции инкремента и декремента соответственно увеличивают
или уменьшают значение операнда на 1. Различают п о с т ф и к с н ы й и пре¬
ф и к с н ы й инкремент и декремент. Н а п р и м е р , выражение x++ возвращает
значение переменной х, а затем увеличивает его на 1, а выражение ++x
увеличивает значение x на 1 и возвращает его.
Операция присваивания в различных языках имеет разное обозначе
ние. Так, в я з ы к а х С, C++, Java операция присваивания обозначается
символом =. Н а п р и м е р , x = y + z;. Я з ы к С позволяет в одном операторе
указывать несколько операций присваивания. Например: x1 = x2 = y + z.
В языках Pascal и A L G O L операция присваивания указывается с и м в о
лами = :. Н а п р и м е р : x:=y+z;. В я з ы к е L I S P операция присваивания обо
значается ф у н к ц и е й SETQ (например, (SETQ x (PLUS y z ) ) ) .
8
8
Операторы
Структурное
программирование
Первоначально все разрабатываемые универсальные я з ы к и п р о
граммирования имели оператор безусловного перехода goto. В настоящее
время разработчики я з ы к о в большей частью придерживаются парадигмы
структурного программирования (программирования без goto).
К о с н о в н ы м достоинствам структурного программирования следует
отнести:
• иерархическое построение программы, включающее только три ос¬
н о в н ы е ф о р м ы управления последовательностью действий: к о м п о
з и ц и я (последовательное выполнение), ветвление (альтернативное
выполнение) и повторение (циклическое выполнение);
29
Курс
Введение в программирование
• представление программы к а к набора блоков управляющих конст¬
рукций с одним входом и одним выходом.
Алгоритм в ы п о л н е н и я структурированной программы может быть
представлен в виде блок-схемы. Такая блок-схема может содержать три
типа узлов:
• функциональные узлы;
• узлы вычисления условия;
• узлы соединения ветвей.
Изображение этих узлов представлено на следующей схеме:
Правильная структурированная программа представляется блоксхемой, в которой существует только одна входящая и одна исходящая ду
га, в любой узел м о ж н о попасть от входящей дуги и из любого узла м о ж
но попасть к выходящей дуге.
Составные
операторы
Каждая из основных ф о р м управления последовательностью дейст
вий имеет в различных языках программирования свои, в значительной
степени синтаксически схожие операторы я з ы к а программирования.
Для создания сложных управляющих к о м п о з и ц и й иногда последо
вательность операторов необходимо указывать к а к один оператор. Для
этой цели служит составной оператор. Синтаксически составной опера
тор может быть указан ключевыми словами begin end (язык Pascal) или
фигурными скобками {} (языки C++, Java, Perl).
Операторы
К операторам выбора относятся:
• i f — условный оператор;
• switch — переключатель.
30
выбора
Лекция 3
Управление последовательностью действий
Операторы выбора осуществляют ветвление. Оператор i f в зависи
мости от значения выражения-условия позволяет выполнить только одну
из двух указанных последовательностей операторов (в большинстве я з ы
ков программирования такая последовательность операторов указывает
ся к а к один составной оператор). Существуют ф о р м ы оператора i f , поз
в о л я ю щ и е задавать вместо второй выполняемой последовательности опе
раторов условие ( i f - e l s e i f - t h e n - e l s e i f - t h e n ) .
Оператор switch в зависимости от значения вычисляемого выраже
н и я позволяет выполнить одну из нескольких указанных последователь¬
ностей операторов.
Например:
switch ( i ) :
{case 0:
case 1:
break;
case 2:
break;
// последовательность операторов
// последовательность операторов
default:
}
Реализация оператора i f достаточно проста: как правило, процессор
поддерживает команды перехода и ветвления.
Реализация оператора switch может быть выполнена в виде таблицы
перехода, состоящей из команд безусловного перехода на соответствую
щ и е фрагменты кода. Вычисляемое выражение оператора switch в этом
случае преобразовывается в значение сдвига по таблице перехода, опре
деляющее выполняемую команду.
Операторы
цикла
Операторы цикла наряду с механизмом рекурсии выражают форму
повторения последовательности действий.
Я з ы к и программирования, как правило, имеют несколько ф о р м
оператора цикла.
В я з ы к е С + + предусмотрено три ф о р м ы оператора цикла:
• for;
• do;
• while.
Ц и к л fo r выполняется заданное число раз, а проверка условия п р и
надлежности счетчика цикла заданному диапазону производится до в ы
полнения операторов, указанных в цикле.
31
Курс
Введение в программирование
Оператор do выполняется до тех пор, пока условие цикла остается
и с т и н н ы м , а проверка условия цикла производится после в ы п о л н е н и я
операторов, указанных в цикле.
Оператор while выполняется до тех пор, пока условие цикла остает
ся и с т и н н ы м , а проверка условия цикла производится до в ы п о л н е н и я
операторов, указанных в цикле.
П р и н я т о считать, что любой оператор цикла состоит из двух частей:
• заголовка цикла, определяющего число выполнений цикла;
• тела цикла, содержащего последовательность выполняемых опера¬
торов (в большинстве случаев указываемую как один составной опе¬
ратор).
Реализация операторов цикла с конечным числом повторений отли
чается от реализации циклов с бесконечным повторением или повторени¬
ем, основанным на некоторых данных. П р и реализации цикла с конечным
числом повторений выделяется специальная область памяти для хранения
этого значения. Цикл for также может относиться как к циклам с конеч
н ы м числом повторений (for ( I = 1; I < 50; I ++){cout << I << endl;}),
так и к циклам с бесконечным повторением ( f o r
= i+j;}).
Операторы
перехода
Д л я выхода из бесконечных ц и к л о в и л и подпрограмм используют
ся операторы перехода. В я з ы к е C + + р е а л и з о в а н ы четыре оператора пе¬
рехода:
• break — прерывает в ы п о л н е н и е цикла, завершая его;
• continue — завершает текущую итерацию в ы п о л н е н и я цикла;
• return — определяет выход из ф у н к ц и и ;
• goto — оператор безусловного перехода на метку.
Операторы
исключений
Некоторые я з ы к и программирования позволяют реализовывать об
работку о ш и б о к , называемых и с к л ю ч е н и я м и , используя операторы и с
ключений. Код, который может инициировать исключение, заключается
в специальный оператор t r y - c a t c h . П р и этом ключевое слово catch опре
деляет действия, в ы п о л н я е м ы е в случае возникновения определенного
исключения. И с к л ю ч е н и е может инициироваться программно или опе
ратором throw (бросок исключения). Некоторые я з ы к и программирова
н и я позволяют передавать обработку исключения вызывающему методу
(так, в я з ы к е Java в сигнатуре метода м о ж н о ключевым словом throws ука¬
зать с п и с о к исключений, при в о з н и к н о в е н и и которых управление будет
возвращено вызывающей программе).
32
Лекция 4
Управление подпрограммами
Лекция 4. Управление подпрограммами
Простые подпрограммы
Определение и активация подпрограмм
Программу м о ж н о рассматривать к а к некоторую иерархическую
структуру, состоящую и з одной главной программы и множества произ¬
вольным образом вызываемых подпрограмм. Точка вызова подпрограм¬
м ы является и точкой возврата из подпрограммы.
Для в ы п о л н е н и я любого выражения транслятор преобразует его в
некоторый код, который и л и может быть сразу аппаратно интерпретиру¬
ем ( м а ш и н н ы й язык) или программно интерпретируем (использование
интерпретатора).
Для выполнения подпрограммы производится ее активация, в р е
зультате чего создаются:
• сегмент кода, содержащий выполняемый код и константы;
• сегмент данных, называемый также записью активации, содержащей
локальные переменные и параметры.
Сегмент кода представляет собой неизменяемую часть, статически
сохраняемую в памяти, а сегмент данных создается заново при каждом
в ы п о л н е н и и подпрограммы.
Каждая активация подпрограммы использует один единожды со¬
зданный сегмент кода.
Подпрограмма может быть реализована к а к процедура или ф у н к ц и я .
Процедура — это подпрограмма, в ы п о л н я ю щ а я определенные действия и
завершающаяся без возврата значения определенного типа.
Результатом в ы п о л н е н и я ф у н к ц и и всегда является возврат некото
рого значения.
П р и выполнении программы текущая выполняемая команда иден
тифицируется двумя указателями:
• CIP-указатель (СшгеМ Instruction Pointer) является указателем теку¬
щей команды сегмента кода;
• CEP-указатель (Current Environment Pointer) является указателем т е
кущей записи активации. CEP-указатель иногда также называется
указателем текущей среды, так к а к определяет среду всех объектов
данных, используемых подпрограммой.
П р и выполнении программы интерпретатор выбирает команду по
CIP-указателю, увеличивает значение этого указателя и выполняет в ы
бранную команду. Если при выполнении команды был выполнен безус33
Курс
Введение в программирование
л о в н ы й переход или вызов подпрограммы, то значение CIP-указателя
опять изменяется. Значение переменной, используемой в подпрограмме,
определяется по CEP-указателю, идентифицирующему конкретную за¬
пись активации.
Последовательный вызов подпрограмм
Запись активации для главной программы создается или перед нача
лом в ы п о л н е н и я программы или в процессе трансляции одновременно с
формированием сегмента кода.
Перед переходом на подпрограмму текущие значения C I P - и C E P указателей сохраняются. Выполнение программы начинается с присваи
вания CEP-указателю адреса записи активации, а CIP-указателю — ссыл¬
ки на первую команду сегмента кода главной программы. П р и каждом
вызове подпрограммы создается новая запись активации этой подпро
граммы, и значение CEP-указателя устанавливается на эту запись актива
ц и и , а значение CIP-указателя — на первую команду фрагмента кода под¬
программы.
П р и возврате из подпрограммы восстанавливаются сохраненные
значения C I P - и CEP-указателей и удаляется запись активации.
Место сохранения значений CIP-указателя и CEP-указателя иногда
называют точкой возврата. Точка возврата представляет собой системный
объект, сохраняемый, как правило, в записи активации.
П р и последовательном вызове подпрограммы (реализуемом иногда
как копирование подпрограммы) в процессе в ы п о л н е н и я может созда
ваться множество записей активации подпрограммы, но в каждый от
дельный момент времени хранится и используется только одна запись ак
тивации, т.е. перед созданием новой записи активации прежняя запись
активации должна быть удалена.
Иногда в реализациях для достижения наибольшего быстродействия
жертвуют некоторым количеством требуемой памяти: место под запись
активации выделяется статически при к о м п и л я ц и и (во фрагменте кода) и
при каждом вызове происходит только повторная и н и ц и а л и з а ц и я записи
активации. В этом случае н и к а к а я подпрограмма не может одновременно
иметь более одной записи активации, что значительно сужает возможно¬
сти программиста. Такая модель в ы п о л н е н и я присуща большинству
трансляторов я з ы к а F O R T R A N .
Для аппаратной реализации вызова подпрограммы с заранее ф и к с и
рованной записью активации достаточно только CIP-указателя, сохраня¬
емого командой перехода с возвратом.
Если место для записи активации должно выделяться динамически,
то это, как правило, реализуется с п о м о щ ь ю стека.
34
Лекция 4
Управление подпрограммами
Стек создается в свободной области памяти. П р и вызове подпро
граммы созданная запись активации помещается в стек. П р и этом значе
н и е указателя стека увеличивается с учетом размера выделяемого прост
ранства. П р и удалении записи активации з н а ч е н и е указателя стека
уменьшается с учетом освобождаемого пространства. Выделение и осво
бождение памяти в стеке происходит с одного конца и фиксируется ука¬
зателем стека.
Такая реализация позволяет создавать для одной подпрограммы н е
сколько записей активации, которые будут последовательно заноситься в
стек.
На рис. 4.1 представлена организация памяти, используемая при в ы
п о л н е н и и программы на я з ы к е С.
Вся память программы делится на статическую, определяемую при
трансляции, и динамическую, содержание которой формируется в п р о
цессе выполнения. Стек располагается в динамической области памяти.
Статическая область памяти
Сегменты кода
Динамическая область памяти — стек
Запись активации вызванной
подпрограммы A
Запись активации вызванной
подпрограммы B
Свободное пространство стека
Динамическая область памяти — куча
Свободное пространство кучи
Объекты, созданные операцией
new
Рис. 4.1.
35
<- Указатель стека
Вершина стека, опреде¬
ляемая указателем стека,
и з м е н я е м ы м в направ
лении |
Курс
Введение в программирование
Также в динамической области памяти располагается куча, прост
ранство которой используется под динамически создаваемые объекты.
Рекурсивный вызов подпрограмм
П р и м е н е н и е стека для хранения записей активации позволяет реализовывать не только последовательный вызов подпрограмм, но и рекур¬
с и в н ы й вызов.
Рекурсивным вызовом подпрограммы называется вызов подпро
граммы из самой себя. П р и n вызовах подпрограммы A в стек будет после¬
довательно добавлено n записей активации этой подпрограммы. Послед¬
н и й вызов подпрограммы A будет завершен первым, и его запись актива¬
ц и и будет первой удалена из стека.
Примером использования рекурсии может служить программа в ы
числения факториала n! = (n*(n-1)!), 0! = 1.
П р и м е р подпрограммы на я з ы к е С:
i n t f a c t o r i a ( i n t n)
{ i f (n) return n* f a c t o r i a ( n - l ) ;
e l s e return 1;
}
В некоторых случаях без п р и м е н е н и я рекурсии задачу решить прак
тически невозможно. Хорошо известен пример программирования алго
ритма ханойских башен. Условия задачи состоят в следующем: есть три
башни; первая башня состоит из колец, диаметр которых увеличивается
сверху вниз. Задача заключается в программировании алгоритма, обеспе¬
чивающего перемещение колец с первой башни на вторую по одному с
в о з м о ж н ы м использованием вспомогательной третьей башни таким об¬
разом, чтобы все кольца оказались на второй башне и их диаметр увели¬
чивался сверху вниз. Алгоритм р е ш е н и я этой задачи посредством рекур
сии состоит в предположении, что эта задача решена для n-1 кольца. Тог
да, если при n = 1 р е ш е н и е задачи очевидно, то есть р е ш е н и е и для n
колец.
П р и м е р подпрограммы на я з ы к е С + + , реализующей алгоритм ха¬
нойских башен:
#include " s t d a f x . h "
#include <iostream>
v o i d t o w e r _ 3 ( i n t n, i n t m, i n t k);
i n t m a i n ( i n t argc, _TCHAR* a r g v [ ] )
{
36
Лекция 4
Управление подпрограммами
tower_3 (3,1,3);
return 0;
}
void tower_3(int
лец
n, i n t m, i n t k){ /* n - число перемещаемых ко
m - башня, с которой выполняется перемещение
k - башня, на которую выполняется перемещение */
i f (n==1)
{ //Последнее очевидное перемещение
return ;}
tower_3(n-1,m,6-m-k); /* 6-m-k определяет номер вспомогательной
башни, m - номер башни, с которой
выполняется перемещение
*/
std::cout<<" from "<< m << " t o "<< k<<" n= "<<n-1«std::endl;
tower_3(n-1,6-m-k,k); /* 6-m-k- номер башни, с которой
выполняется перемещение
*/
}
На рис. 4.2 приведен пример выполнения алгоритма ханойских ба
ш е н для трех колец (n указывает количество перекладываемых колец).
-|п|х
Ш
from
from
from
Press
1 to
2
i to
3
2 to
3
any key
n=
n= 2
n= 1
to c o n t i n u e .
4
<
Рис. 4.2. Результат рекурсивного вызова процедуры
Одним и з первых я з ы к о в программирования, допускавших рекур
сию, являлся A L G O L 60. Раньше п р и н ц и п ы реализации записей актива
ц и и трансляторами я з ы к а F O R T R A N н е позволяли применять рекурсию,
но последняя версия компилятора языка F O R T R A N 90 это допускает.
Подпрограммы A и B называются взаимно рекурсивными, если под
программа A вызывает B , а подпрограмма B вызывает A .
Я з ы к и программирования, для которых традиционно используются
однопроходные компиляторы, для реализации взаимной рекурсии долж37
Курс
Введение в программирование
н ы вводить предварительное определение подпрограммы. Это объясняет
ся тем, что п р и взаимно рекурсивном вызове подпрограмм A и B , в мо¬
мент вызова B и з A подпрограмма B должна быть уже определена, а в мо¬
мент вызова A и з B подпрограмма A должна быть определена. Такой м е
ханизм используется в языках Pascal и Ada.
Я з ы к Pascal н е требует указания сигнатуры ф у н к ц и и и л и процедуры
в том случае, если ее определение расположено в коде программы до ее
вызова. В противном случае используется предварительное определение,
указываемое ключевым словом forward.
На рис. 4.3 приведен код модуля на я з ы к е Pascal (созданного в среде
Delphi), иллюстрирующий предварительное объявление ф у н к ц и и A .
Рис. 4.3. Предварительное объявление ф у н к ц и и
38
Лекция 4
Управление подпрограммами
Следует отметить, что к о м п и л я ц и я программ, удовлетворяющих
стандарту языка программирования, различными трансляторами может
создавать различный в ы п о л н и м ы й код. П р и этом очень часто к о м п и л я т о
р ы несколько «расширяют» диапазон возможностей, предоставляемых
стандартом языка программирования. Такая ситуация будет приводить к
ограничению использования «расширенного» синтаксиса программы с
другими компиляторами.
39
Курс
Введение в программирование
Л е к ц и я 5. У п р а в л е н и е д а н н ы м и и п а р а м е т р а м и
подпрограмм
Управление данными
При интерпретации выполняемого выражения, содержащего дан
ные, к о м п и л я т о р д о л ж е н о д н о з н а ч н о "понимать" у к а з ы в а е м ы е и д е н
т и ф и к а т о р а м и о п е р а н д ы в ы р а ж е н и я . Так, о д и н и тот ж е и д е н т и ф и к а
т о р может в р а з л и ч н ы х частях п р о г р а м м ы и с п о л ь з о в а т ь с я д л я о б о з н а
ч е н и я р а з н ы х д а н н ы х . И д е н т и ф и к а т о р может быть м е т к о й и л и и м е н е м
п о д п р о г р а м м ы . В п е р в о м случае п р и т р а н с л я ц и и в ы р а ж е н и я к о м п и л я
т о р д о л ж е н и н и ц и и р о в а т ь с о о б щ е н и е об о ш и б к е к о м п и л я ц и и . В з а в и
с и м о с т и от того, у к а з ы в а е т л и и д е н т и ф и к а т о р н а п е р е м е н н у ю и л и н а
константу, к о м п и л я т о р т а к ж е д о л ж е н п р е д п р и н и м а т ь р а з л и ч н ы е д е й
ствия.
И м я в программе может быть простым или составным. К простым
именам относятся имена переменных, имена подпрограмм, имена поль
зовательских типов данных. Составное имя ссылается на элемент некото
рой структуры и записывается к а к простое и м я и следующие за н и м опе¬
р а ц и и к в а л и ф и к а ц и и или индексации имени. Н а п р и м е р , выражение
a r r a y 1 [ 3 ] ссылается на третий э л е м е н т м а с с и в а , а в ы р а ж е н и е
record1. f i e l d 2 ссылается на значение поля f i e l d 2 структуры record1.
Для управления д а н н ы м и к о н к р е т н ы е идентификаторы подпро¬
граммы д о л ж н ы быть сопоставлены к о н к р е т н ы м объектам данных. Такое
сопоставление иногда называется ассоциацией. В момент создания запи
си активации устанавливается множество ассоциаций, сопоставляющих
идентификаторы с текущими объектами данных. Такое множество ассо¬
ц и а ц и й определяет среду ссылок подпрограммы.
Среда ссылок подпрограммы включает среду глобальных ссылок, сре¬
ду локальных ссылок, среду нелокальных ссылок и среду предопределен¬
ных ссылок.
Среда локальных ссылок образуется л о к а л ь н ы м и п е р е м е н н ы м и ,
ф о р м а л ь н ы м и параметрами, а также подпрограммами, определенными
внутри текущей подпрограммы.
Среда глобальных ссылок формируется ассоциациями, которые со¬
зданы при активации главной программы. Среда нелокальных ссылок со¬
держит как среду глобальных ссылок, так и множество ассоциаций, с ф о р
мированных для доступных далее в программе, но еще не созданных пе¬
ременных.
Область видимости ассоциации в подпрограмме определяется вклю¬
ч е н и е м этой ассоциации в среду ссылок подпрограммы. П р и этом, если
40
Лекция 5
Управление данными и параметрами подпрограмм
имело место переопределение глобального идентификатора локальным
идентификатором, то ассоциация для глобального идентификатора и с
ключается из среды глобальных ссылок подпрограммы.
Динамическая область видимости каждой ассоциации определяется
совокупностью записей активации подпрограмм, включающих данную
ассоциацию в среду ссылок подпрограммы.
На один и тот ж е объект данных м о ж н о ссылаться посредством раз
личных и м е н — например, если в подпрограмме доступен идентификатор
глобальной переменной и эта же переменная передается по ссылке как
ф о р м а л ь н ы й параметр подпрограммы. Различные идентификаторы, су
ществующие в среде ссылок для ассоциации с одним и тем ж е объектом
данных, иногда называются псевдонимами.
Использование псевдонимов может приводить к различным оши¬
бочным ситуациям. К тому ж е , наличие в подпрограмме псевдонимов о с
ложняет процесс оптимизации кода, в ы п о л н я е м ы й компилятором. На¬
п р и м е р , если при в ы п о л н е н и и последовательности двух операторов
int1=5*x; int2=8*y; значение переменной i n t 1 нигде в программе не и с
пользуется, то при оптимизации программы первый оператор может быть
упразднен. Н о если переменная i n t 1 является псевдонимом переменной
y, то такая оптимизация приведет к о ш и б к е вычисления, и, следователь
но, потребуются дополнительные проверки.
Под статической областью видимости понимается фрагмент кода
программы, в котором идентификатор ссылается на к о н к р е т н ы й объект.
Статическая область видимости определяет объект, на который ссы
лается идентификатор в коде программы, а динамическая область види
мости формируется ассоциациями, созданными во время выполнения
программы.
Блочно-структурированные языки
программирования
В блочно-структурированных языках программирования программа
записывается как множество иерархически вложенных блоков опреде¬
ленной структуры.
Блочно-структурированные я з ы к и программирования м о ж н о под
разделить на строго блочно-структурированные я з ы к и и просто блочноструктурированные я з ы к и .
В строго б л о ч н о - с т р у к т у р и р о в а н н ы х я з ы к а х в начале каждого б л о
к а располагается область о б ъ я в л е н и й , а за н е й следует ф р а г м е н т кода.
И н а ч е говоря, в строго б л о ч н о - с т р у к т у р и р о в а н н ы х я з ы к а х п р о г р а м м и
р о в а н и я не допускается о б ъ я в л е н и е п е р е м е н н ы х в л ю б о м месте фраг¬
мента кода.
41
Курс
Введение в программирование
К строго блочно-структурированным я з ы к а м п р о г р а м м и р о в а н и я от
носятся я з ы к и A L G O L 60, Pascal, P L / I .
К а ж д ы й блок в блочно-структурированном я з ы к е п р о г р а м м и р о в а
н и я вводит новую среду локальных ссылок.
Следующий п р и м е р иллюстрирует блочную структуру п р о г р а м м ы на
я з ы к е Pascal.
program P r o j e c t 1 ;
procedure P1();
procedure P2();
{Вложенная процедура}
var i:Integer;
begin
end;
begin
{Код процедуры P1}
end;
begin
{Код главной программы P r o j e c t 1 }
end.
В я з ы к е Object Pascal по у м о л ч а н и ю п р и л о ж е н и я создаются к а к н а
бор модулей, подключаемых к л ю ч е в ы м словом uses. Следующий п р и м е р
иллюстрирует блочную структуру п р о г р а м м ы на я з ы к е Object Pascal,
представленную в виде одного модуля.
program P r o j e c t 2 ;
{Начало программы}
uses
Windows, Messages, S y s U t i l s ,
Variants,
Classes,
Graphics,
C o n t r o l s , Forms,
Dialogs,
StdCtrls;
{$R *.res}
{$R *.dfm}
{Имя DFM-файла должно совпадать
с именем модуля (блока). }
{Для получения единого модуля на языке Object P a s c a l
при автоматическом создании приложения в среде D e l p h i файл
Unit1.dfm следует переименовать в Project2.dfm, а код модуля
Unit1.pas перенести в модуль Project2.pas}
type
{Объявление нового типа окна формы TForm1 }
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
ListBox1: TListBox;
42
Лекция 5
Управление данными и параметрами подпрограмм
Edit1: TEdit;
procedure B u t t o n 1 C l i c k ( S e n d e r : TObject);
procedure B u t t o n 2 C l i c k ( S e n d e r : TObject);
procedure L i s t B o x 1 C l i c k ( S e n d e r : TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
{Начало области объявлений }
Form1: TForm1;
i : Integer;
procedure TForm1.Button1Click(Sender: TObject);
begin
Edit1.Text:='Button1';
end;
procedure TForm1.Button2Click(Sender: TObject);
var i:Integer;
procedure P1();
{Вложенная процедура}
var i:Integer;
begin
i:=5;
Edit1.Text:= Edit1.Text+' i= ' + I n t T o S t r ( i ) ;
end;
begin
Edit1.Text:='Button2';
i:=0;
P1 ( ) ;
end;
procedure TForm1.ListBox1Click(Sender: TObject);
begin
Edit1.Text:='ListBox1';
end;
begin
{Начало выполнения программы}
Application.Initialize;
Application.CreateForm(TForm1,
Application.Run;
end.
Form1);
Н а рис. 5.1 отображен результат в ы п о л н е н и я приведенной в ы ш е п р о
граммы (сделан щелчок м ы ш ь ю на к н о п к е Button2, и н и ц и и р у ю щ и й в ы
п о л н е н и е процедуры TFormLButton2CUck и вложенной процедуры P1).
43
Курс
Введение в программирование
•даю
Buitonl
|Button2i=
I
Bution2
:
5
Рис. 5.1. О к н о ф о р м ы
К простым блочно-структурированным я з ы к а м относятся такие
я з ы к и , к а к C и Java, позволяющие формировать область объявления п е
ременных в любом месте блока.
Современные языки программирования, такие как C++, Java, Object
Pascal, относятся к блочно-структурированным языкам программирования,
и при этом программы на этих языках могут состоять из нескольких блоков
(программных модулей), расположенных на верхнем уровне иерархии.
Блочная структура организации программ делает «прозрачной» для
программиста статическую область видимости, определяя правила объяв
л е н и я идентификаторов. Так, если во вложенном блоке объявляется
идентификатор с уже существующим и м е н е м , то это «перекрывает» ссыл¬
ку на о д н о и м е н н ы й идентификатор во внешнем блоке (без квалифика¬
ц и и внешнего идентификатора, когда это позволяет синтаксис я з ы к а
программирования). Все идентификаторы, объявленные во вложенном
блоке, недоступны во в н е ш н е м блоке.
Блок может представлять собой:
• программу (например, program
end. ),
• фрагмент кода, заключенный в скобки блока
(такие к а к begin
end)
• подпрограмму (например, procedure
begin
end; ).
Передача параметров
В н е ш н и е д а н н ы е в подпрограмме могут использоваться, если о н и
являются глобальными объектами для д а н н о й подпрограммы или переда
н ы ей в качестве параметров. В о п и с а н и и подпрограммы указываются
формальные параметры, а в точке вызова подпрограммы задаются ф а к т и
ческие параметры. Ф о р м а л ь н ы й параметр определяет тип передаваемого
44
Лекция 5
Управление данными и параметрами подпрограмм
фактического параметра. Фактический параметр представляет собой вы¬
ражение соответствующего типа.
Различаются следующие способы передачи параметров: по ссылке,
по и м е н и , по значению, по значению-результату, по результату, по значе¬
нию-константе. Набор допустимых способов передачи параметров зави
сит от конкретного языка программирования.
П р и передаче параметров по ссылке в записи активации, создаваемой
при в ы п о л н е н и и подпрограммы, ассоциация для фактического парамет
ра может формироваться в нелокальной среде ссылок (в зависимости от
реализации компилятора). Так, при вызове подпрограммы для парамет
ров, передаваемых по ссылке, формируются указатели, доступные к а к из
вызывающей, так и из вызываемой подпрограммы. Таким образом, при
и з м е н е н и и в вызываемой подпрограмме значения фактического параме¬
тра, переданного по ссылке, в вызывающей программе объект, соответст¬
вующий фактическому параметру, также будет изменен.
П р и передаче параметров по имени в вызываемой подпрограмме до ее
в ы п о л н е н и я происходит замена формальных параметров на фактические.
П р и этом значения фактических параметров вычисляются внутри вызы¬
ваемой подпрограммы.
П р и передаче параметров по значению в вызываемой подпрограмме
создается псевдоним фактического параметра (копия фактического пара
метра), значение которого присваивается формальному параметру под
программы. П р и таком способе передачи параметров и з м е н е н и я , произ¬
веденные в вызванной процедуре над значением фактического парамет¬
ра, будут не видны далее в вызывающей подпрограмме.
П р и передаче параметров по значению-результату
измененное значе
н и е фактического параметра возвращается вызывающей подпрограмме.
Однако, в отличие от передачи параметров по ссылке, при д а н н о м спосо¬
бе сначала в момент вызова подпрограммы значение фактического пара¬
метра присваивается соответствующему формальному параметру вызыва
емой подпрограммы, и все изменения выполняются над формальным па¬
раметром, а не над ссылкой на фактический параметр. П р и завершении
вызываемой подпрограммы текущее значение формального параметра
присваивается обратно фактическому параметру. Такой тип передачи па
раметров был применен в я з ы к е A L G O L - W .
П р и передаче параметров по результату текущее значение формаль¬
ного параметра присваивается обратно фактическому параметру при за¬
вершении вызываемой подпрограммы, но первоначальное значение фак¬
тического параметра вызываемой подпрограмме не передается. Формаль¬
н ы й параметр подпрограммы должен быть и н и ц и и р о в а н подпрограммой
(реализация может позволять и н и ц и а л и з а ц и ю по умолчанию в соответст¬
вии с типом данных параметра).
45
Курс
Введение в программирование
П р и передаче параметров по значению-константе
значение фактиче¬
ского параметра не может быть изменено. Такой способ передачи параме¬
тров может быть реализован и как частный случай передачи параметра по
значению, и как передача параметра по ссылке на константное выраже¬
ние, что однозначно гарантирует неизменность фактического параметра
вызывающей подпрограммы.
В большинстве случаев я з ы к и программирования используют один
ли два способа передачи параметров. Так, я з ы к программирования С поз
воляет только передачу параметров по значению (ссылка реализуется как
значение указателя). В я з ы к е программирования Pascal допускается два
способа передачи параметров: по значению и по ссылке.
В следующей таблице приведены фрагменты кода, иллюстрирующие
способы передачи параметров в языках программирования С и Pascal.
Способ
передачи
параметров
Pascal
C
Передача
параметров
по значению
procedure P 1 ( i :
integer);
begin
/ / 1 . Передача значения
i:=0;
end;
/ / В ы з о в подпрограммы
v o i d procedure
P1( i n t i )
{i=0; }
i=10;
P1 ( i ) ;
/ / 2 . Передача указателя
на значение
v o i d procedure
P1(int * i )
{ *i=*i+1;}
/ / В ы з о в подпрограммы
i=10;
P1
Передача
параметров
по ссылке
procedure P1(var i :
integer);
begin
i:=0;
end;
Существующие в настоящее время средства автоматической генера
ц и и кода вызова подпрограммы по о п и с а н и ю интерфейса вводят понятие
входных и выходных параметров (помечаемых как i n и out). П р и этом в
зависимости от типа параметра и определения его к а к входного и / и л и в ы
ходного компилятор автоматически выбирает походящий для д а н н о й ре¬
ализации способ передачи параметров.
46
Лекция 5
Управление данными и параметрами подпрограмм
Функции и процедуры
К а к уже было сказано в предыдущей л е к ц и и , подпрограмма в боль
шинстве я з ы к о в программирования может быть реализована двумя с п о
собами: как ф у н к ц и я и как процедура.
Е с л и п о д п р о г р а м м а реализуется к а к ф у н к ц и я , то о н а п р и завер¬
ш е н и и должна возвращать значение определенного типа (например,
return 0;). П о д п р о г р а м м а - ф у н к ц и я может указываться в выражениях.
Подпрограмма-функция также может быть передана подпрограмме
в качестве фактического параметра, например,
(procedure P1 ( i : i n t e g e r ;
function
P2(j:integer):integer);).
П о м и м о использования глобальных переменных, некоторые я з ы к и
программирования позволяют делать локальные переменные подпро
грамм доступными для других подпрограмм, выполняющихся вне теку
щей записи активации д а н н о й подпрограммы. Это может быть реализо
вано как экспорт данных (externs в я з ы к е С, uses в я з ы к е Pascal), и в та
ком случае экспортируемая локальная переменная должна быть доступна
вне записи активации. Поэтому ее, как правило, размещают в сегменте
кода подпрограммы.
К способам реализации совместного использования данных отно
сится и механизм я в н о организуемой общей среды. Все объекты данных,
которые предполагается использовать в ряде подпрограмм, могут быть
п о м е щ е н ы в такую общую среду. Этот механизм реализуется в таких я з ы
ках программирования, как С (переменные помечаются к а к extern), Ada
(переменные указываются в пакете), F O R T R A N (переменные задаются в
блоке C O M M O N ) . В объектно-ориентированных языках программирова
н и я совместное использование данных может быть реализовано через мо¬
д и ф и к а т о р ы доступа переменных членов классов.
Другие я з ы к и программирования (LISP, A P L ) для реализации совме
стного использования данных п р и м е н я ю т механизм динамической обла
сти видимости, при котором выполняется восходящий п о и с к ассоциации
для переменной (ассоциация для нелокальной переменной подпрограм
м ы последовательно ищется во всех средах ссылок выполняемых ранее
подпрограмм).
47
Курс
Введение в программирование
Глава 3. Структуры данных
Л е к ц и я 6. П р о с т ы е т и п ы д а н н ы х
Переменные и константы
Будем называть объектом данных один или несколько однотипных
элементов данных, рассматриваемых программой как одно простое или
составное целое.
Объекту данных присущи такие атрибуты, как тип, адрес памяти,
присвоенное значение, имя.
П е р е м е н н ы е и константы — это объекты данных. П р и создании п е
ременной или константы им назначается и м я , называемое иногда иден
тификатором. В отличие от переменной, атрибут «значение» объекта д а н
ных «константа» не может быть изменен в процессе в ы п о л н е н и я про¬
граммы.
Объявление объектов данных
Перед использованием в программе л ю б о й объект д а н н ы х должен
быть объявлен. Однако некоторые я з ы к и допускают н е я в н о е объявле
ние. Так, в я з ы к е F O R T R A N к о м п и л я т о р определяет тип используемой,
но предварительно не объявленной п е р е м е н н о й по первому символу
и м е н и , а в я з ы к е Perl н е я в н о е объявление п е р е м е н н о й происходит п р и
п р и с в а и в а н и и ей начального значения. Н е к о т о р ы е я з ы к и в ы п о л н я ю т
н е я в н о е объявление переменных, используемых в качестве счетчиков
циклов.
Оператор объявления сообщает компилятору и н ф о р м а ц и ю об иден¬
тификаторах и типах данных, назначаемых объектам данных, и о предпо¬
лагаемом времени ж и з н и этих объектов (глобальная или локальная пере
менная, переменная — член класса, статическая переменная и т.п.).
П р и объявлении объекта данных в зависимости от типа этого объек
та и я з ы к а программирования возможно выделение памяти под этот объ
ект при объявлении или при последующем создании этого объекта.
В я з ы к е С + + для объявления новых и м е н в текущей области види
мости предназначаются операторы объявления.
Например: i n t i , j ; f l o a t m, n;
Оператор объявления в я з ы к е С + + может указываться в любом до¬
пустимом месте программы.
48
Лекция 6
Простые типы данных
В языке С + + каждый оператор объявления завершается симво
л о м к о н ц а о п е р а т о р а (точка с з а п я т о й ) . В о п е р а т о р е о б ъ я в л е н и я м о
ж е т о б ъ я в л я т ь с я н е с к о л ь к о о б ъ е к т о в д а н н ы х одного т и п а , п е р е ч и с л я
е м ы х через з а п я т у ю . Л ю б о й о п е р а т о р о б ъ я в л е н и я н а ч и н а е т с я с к л ю ч е
вого с л о в а и л и и д е н т и ф и к а т о р а , у к а з ы в а ю щ е г о т и п о б ъ я в л я е м о г о
объекта.
Объявляемыми объектами данных могут быть названия типов и име¬
на объектов.
Объявление определяет и м я внутри области видимости. И м я , о б ъ
я в л я е м о е внутри блока, класса, ф у н к ц и и и л и пространства и м е н , я в л я
ется л о к а л ь н ы м . Б л о к в я з ы к е С + + заключается в ф и г у р н ы е с к о б к и . Е с
л и в н е блока существуют глобальные имена, обозначаемые теми ж е
и д е н т и ф и к а т о р а м и , то о н и становятся с к р ы т ы внутри блока и к н и м
следует обращаться, используя оператор р а з р е ш е н и я области видимос¬
ти, н а п р и м е р :
int i 1 ;
// Объявление глобальной переменной
v o i d metod1() {
i n t i 1 ; // Объявление локальной переменной
i1=22; // Доступ к локальной переменной метода
::i1=44; // Доступ к глобальной переменной
{ i n t i 1 ; // Объявление локальной переменной
i1=33;
// Доступ к локальной переменной блока
}
i1=44; // Доступ к глобальной переменной
В я з ы к е С + + объявления применяются для создания нового и м е н и ,
используемого в приложении (имя может указывать н е только объект
данных). Объявления позволяют:
• специфицировать класс памяти, т и п и область действия объекта;
• инициализировать объект начальным значением;
• назначать имена константе (при объявлении перечислимого типа);
• объявлять н о в ы й т и п ( c l a s s , s t r u c t и union);
определять с и н о н и м существующего типа (typedef);
специфицировать шаблон классов или ф у н к ц и й (template);
специфицировать пространство и м е н (namespace);
специфицировать класс памяти, т и п и область действия подпро¬
граммы.
Отметим, что термин «объявление» означает только указание, к а к и м
образом объявляемое и м я будет интерпретироваться компилятором.
В я з ы к е С + + п р и каждом объявлении локального объекта под него
выделяется память.
•
•
•
•
49
Курс
Введение в программирование
Например:
// Объявление и инициализация локального объекта в цикле {do {
char char1 = _ g e t c h ( ) ;
if(
(char1
== NULL ) continue;
return
(char1);
} w h i l e ( 1 );
Удаление объекта, который был объявлен в цикле, происходит после
каждой итерации, п р и выходе из блока или при передаче управления в
точку, расположенную в ы ш е объявления этого объекта.
Процедура удаления объекта в я з ы к е С + + может включать н е толь
ко удаление объекта из памяти (освобождение памяти), н о и выполнение
деструкторов (для объектов типа класса).
В я з ы к е Java объявления переменной могут указываться в любом до¬
пустимом месте программы.
Например:
boolean b1=true;
// Оператор присваивания задается символом =
char c1 = ' N' ;
i n t int1=123;
И м е н а могут иметь следующие элементы я з ы к а Java:
пакет, определяемый оператором package;
тип, вводимый определением класса или интерфейса;
поле, являющееся переменной типа класса и л и типа интерфейса;
группа методов типа класса или типа интерфейса;
переменная, я в л я ю щ а я с я формальным параметром метода;
переменная, я в л я ю щ а я с я локальной переменной блока;
метка оператора.
Если и м я или выражение означает переменную или значение п р о
стого типа, тогда тип этой переменной или значения называется типом
и м е н и или выражения.
В я з ы к е Object Pascal оператор объявления может указываться толь
ко в области объявлений, определяемой ключевым словом var.
Например:
•
•
•
•
•
•
•
var
ch1: Char;
{Оператор объявления в языке Object P a s c a l }
begin
ch1 := Chr(65);
{ Оператор присваивания задается символами
:=}
end;
50
Лекция 6
Простые типы данных
Типы данных
Тип данных назначается объекту данных п р и его объявлении и опре
деляет значения, которые может принимать объект данного типа, а также
операции, которые используются для манипуляции над объектами задан¬
ного типа.
Современные я з ы к и программирования, к а к правило, могут иметь
набор простых типов, являющихся встроенными в д а н н ы й я з ы к програм
мирования, и средства для создания производных типов.
Объектно-ориентированные я з ы к и программирования позволяют
определять т и п ы класса.
Реализация простых типов данных заключается в способе представ
л е н и я значений данного типа в компьютере и в наборе операций, поддер
живаемых для данного типа.
Типы данных языка С++
Тип данных определяет размер памяти, выделяемой под переменную
данного типа при ее создании.
C++ поддерживает следующие т и п ы данных:
• базовые типы. Б а з о в ы е т и п ы указываются з а р е з е р в и р о в а н н ы м и
ключевыми словами, и их н е надо определять.
• производные типы. П е р е м е н н ы е этих типов создаются к а к с исполь
зованием базовых типов, так и типов классов. Это структуры, объе
д и н е н и я , указатели, массивы.
• типы класса. Экземпляры этих типов называются объектами.
Базовые т и п ы я з ы к а С + + м о ж н о подразделить на две группы: цело¬
ч и с л е н н ы е и вещественные. Существует е щ е ключевое слово void, кото¬
рое используется для описания типа подпрограмм, н е имеющих возвра
щаемого значения, и л и п р и указании параметров подпрограмм неизвест¬
ного типа.
В я з ы к C++ включены следующие основные базовые т и п ы (их раз
мер приведен для компилятора Visual C++):
char
signed
char
unsigned
char
Символьный тип. Диапазон значений — от —128 до 127.
Содержит один символ или строку символов. К а ж д ы й
символ представляется одним байтом. Компилятор различает
как отдельные следующие типы: char, signed char
и unsigned char.
Символьный тип. Диапазон значений — от 0 до 255.
Каждый символ представляется одним байтом
(значение в диапазоне от 0 до 255).
51
Курс
short
signed
short
Введение в программирование
Целый тип. Диапазон значений от —32768 д о 32767.
С о к р а щ е н н о е обозначение типа short i n t . Д л и н а этого типа
вне зависимости от используемого компилятора всегда
больше или равна д л и н е значения типа char и м е н ь ш е или
равна длине значения типа i n t .
unsigned Беззнаковый целый тип.
short
Диапазон значений — от 0 до 65535.
int
signed
int
Целый тип. Диапазон значений от —2147483648
до 2147483647.
Д л и н а этого типа вне зависимости от используемого
компилятора всегда больше или равна д л и н е значения
типа short i n t .
В общем случае размер типа i n t я з ы к а C++ зависит
от конкретной реализации.
unsigned
int
Беззнаковый целый тип. Диапазон значений — от 0
до 4294967259.
intn
Целый т и п , размер в битах которого определяется
значением n, и может быть равным 8, 16, 32 или 64 битам.
long
signed
long
Целый тип.
Диапазон значений от -2147483648 д о 2147483647.
С о к р а щ е н н о е обозначение типа long i n t .
unsigned
long
Беззнаковый целый тип.
Диапазон значений — от 0 до 4294967259.
float
Тип данных с плавающей точкой.
Диапазон значений — от 3.4Е-38 до 3.4Е+38.
double
Тип данных с плавающей точкой двойной точности.
Диапазон значений от 1.7Е-308 до 1.7Е+308.
Д л и н а типа double вне зависимости от используемого
компилятора всегда больше или равна д л и н е типа f l o a t
и короче или равна д л и н е типа long double.
long
double
Тип данных с плавающей точкой двойной точности,
длина которого равна д л и н е значений типа double.
Типы double и long double имеют одинаковое представление,
но компилятор трактует их к а к различные типы.
Размер памяти, выделяемой под каждый тип данных я з ы к а С \ С + + ,
в некотором смысле зависит от используемой платформы и компилятора.
Однако все компиляторы гарантируют, что для типа short памяти всегда
выделяется м е н ь ш е и л и столько ж е , сколько и для типа i n t , а тип long все¬
гда «длиннее» или равен типу i n t .
Символьные т и п ы char и unsigned char представляют значение с и м
вола, реализуемое одним байтом. Д л я использования символов в к о д и
ровке Unicode я з ы к С + + предоставляет тип w c h a r t , в котором под каж
д ы й символ отводятся два байта.
52
Лекция 6
Простые типы данных
Ключевое слово typedef я з ы к а С + + позволяет объявить новое имя
существующего типа.
Например:
typedef i n t my_integer;
my_integer i1=0;
Создание псевдонима для типа значительно облегчает процесс изме
н е н и я типа переменных в уже отлаженном коде.
Символьным литералом или символьной константой называется
символ, заключенный в одинарные кавычки. Целые литералы представ¬
ляют целочисленные константы в десятичном, восьмеричном или шестнадцатеричном виде.
Восьмеричные литералы начинаются с символа 0, а шестнадцатер и ч н ы е — с символов 0x.
После литерала может быть указан суффикс, определяющий его тип:
U — unsigned i n t , L — long i n t .
Например:
00
oxffff
10L
//
Восьмеричное значение, равное 0
// Шестнадцатеричное значение, равное 65535
// Значение типа long i n t
При записи шестнадцатеричных литералов каждый знак может прини
мать значение от 0 до 15. Для записи значений от 10 до 15 принято исполь
зовать следующие символы: a — 10, b — 11, c — 12, d — 13, e — 14 и f — 15.
Литералы с плавающей точкой могут записываться в двух формах:
вещественной и экспоненциальной.
Например:
1.53
32.24e-12// Экспоненциальная форма записи литерала
Литералы с плавающей точкой могут использоваться для инициализации
значений переменных вещественного типа (float, double или long double).
Преобразование типов в языке С++
Я з ы к C++ позволяет выполнять преобразование значения одного
типа в значение другого типа. Преобразование типа может быть я в н ы м и
н е я в н ы м . Я в н о е преобразование называется приведением типов.
Для явного приведения типов можно использовать две ф о р м ы записи:
53
Курс
Введение в программирование
• без указания дополнительной и н ф о р м а ц и и для преобразования типа
(перед преобразуемой переменной в скобках указывается и м я типа,
к которому она приводится).
Например:
std: :cout <<"strlen="«(long)strlen(pArr1);
• с указанием дополнительной и н ф о р м а ц и и для преобразования типа
(используются
операторы
static_cast,
dynamic_cast,
reinterpret_cast и const_cast).
Например:
std: :cout <<"strlen="«static_cast<long>(strlen(pArr2));
Вторая форма явного преобразования типов более предпочтительна,
поскольку несет в себе дополнительную и н ф о р м а ц и ю , позволяющую со¬
кратить число возможных ошибок.
Дополнительная и н ф о р м а ц и я о приводимом типе может быть указа¬
на следующими операторами:
• s t a t i c _ c a s t — выполняет преобразование родственных типов;
• const_cast — выполняет приведение константных выражений;
• dynamic_cast — используется для динамического преобразования т и
па, реализуемого на этапе выполнения;
• r e i n t e r p r e t _ c a s t — выполняет преобразование н е связанных между
собой типов.
Преобразование типов выполняется для значений переменных п р и
вычислении выражений и оказывает в л и я н и е на тип результата. Преобра
зование типов н е изменяет типа самих переменных, участвующих в выра¬
жении.
Типы данных языка object PASCAL
Все переменные и константы, используемые в программе, всегда
принадлежат какому-либо типу. Вызов ф у н к ц и и также возвращает значе¬
н и е определенного типа.
Типы данных языка Object Pascal можно разбить на следующие группы:
базовые типы данных:
• целочисленный тип;
• действительный тип;
• логический тип;
• символьный т и п ;
• строковый тип;
54
Лекция 6
Простые типы данных
производные типы данных;
простые типы данных:
• порядковый тип;
• перечислимый тип;
структурированные типы данных:
• множества;
• массивы;
• записи;
• файлы;
• объектный тип (тип класса);
• тип ссылки на класс;
указатели;
процедурный тип данных.
В я з ы к Object Pascal включены следующие базовые т и п ы данных:
• Целочисленные т и п ы
Тип
Диапазон значений
Формат
Integer
—2147483648..2147483647
signed 32-bit
Cardinal
0..4294967295
unsigned 32-bit
Shortint
—128..127
signed 8-bit
Smallint
—32768..32767
signed 16-bit
signed 32-bit
Longint
—2147483648..2147483647
Int64
—2 63..2 63 — 1
signed 64-bit
Byte
0..255
unsigned 8-bit
Word
0..65535
unsigned 16-bit
Longword
0..4294967295
unsigned 32-bit
Л
Л
Действительные т и п ы
Тип
Диапазон значений
Real
5.0 * 10 —324 .. 1.7 * 10 308
Real48
Single
Размер в байтах
л
л
л
л
л
л
2.9 * 10 —39 .. 1.7 * 10 38
1.5 * 10 —45 .. 3.4 * 10 38
Double
5.0 * 10 —324 .. 1.7 * 10 308
Extended
3.6 * 10 —4951 .. 1.1 * 10 4932
л
л
л
л
8
6
4
8
10
Comp
—2 63+1 .. 2 63 —1
8
Currency
—922337203685477.5808..
922337203685477.5807
8
л
Л
55
Курс
Введение в программирование
Д л я указания значения действительного типа м о ж н о использовать
э к с п о н е н ц и а л ь н ы й формат (например, значение 1.3Е-5 эквивалентно
1.3*10-5).
• Логические т и п ы
Тип
Диапазон значений
Размер в байтах
Boolean
True или False
1
ByteBool
True или False
1
WordBool
True или False
2
LongBool
True или False
4
Символьные т и п ы
Тип
Диапазон значений
Размер в байтах
Char
ANSI-символ
1
AnsiChar
ANSI-символ
1
WideChar
Unicode-символ
2
Строковые т и п ы
Тип
Максимальная длина
string
Определяется директивой
компилятора $ H
ShortString
255 символов
Размер в байтах
От 2 до 256 байт
AnsiString
(длинная
строка)
А
От 4 байт
до 2 Гбайт
А
От 4 байт
до 2 Гбайт
~2 31 символов
WideString
(Символы
Unicode)
~2 30 символов
Д л я строковых переменных выполняются следующие правила:
• Строки могут быть постоянной или переменной длины: п р и объяв¬
лении строки м о ж н о указать только идентификатор и л и идентифи¬
катор и в квадратных скобках длину строки.
• Значение строки указывается в одинарных кавычках или к а к после
довательность ASCII -символов, перед каждым из которых ставится
знак #.
• Доступ к символу строки м о ж н о выполнять п о индексу, указываемо
му в квадратных скобках (например, MyString[7] := 'n';).
56
Лекция 6
Простые типы данных
Например:
var
S1: s t r i n g ;
{Объявление строковой переменной
произвольной длины}
S2: s t r i n g [ 2 ] ; {Объявление строковой переменной
длиной 2 символа}
Строки типа A n s i S t r i n g также называют д л и н н ы м и строками (long
s t r i n g ) , представляющими динамически размещаемые строки, длина к о
торых ограничена только доступной памятью. Такие строки используют
1-байтовое представление ANSI-символов.
Реально переменная типа A n s i S t r i n g является указателем, состоя
щ и м из 4 байт. Если строка пустая (ее длина равна 0), то указатель равен
nil и для хранения строки н и к а к о й памяти н е выделяется. Если строка н е
является пустой, то данная переменная указывает на динамически разме
щ а е м ы й блок памяти, содержащий значение строки, на 32-битовое значе
н и е д л и н ы строки и на 32-битовое значение счетчика ссылок на строку.
Несколько идентификаторов строк могут ссылаться на одну строку.
П р и этом и м н е будет выделяться дополнительная память, а только будет
выполняться увеличение счетчика ссылок.
Константы в языке OBJECT PASCAL
Объявление переменных выполняется в секции, начинающейся с
ключевого слова var. Ключевое слово const предназначено для объявления
констант.
Константами могут быть простые значения или значения типа запи
си, массива, ф у н к ц и и и указателя.
П р и объявлении константного указателя его сразу необходимо ини¬
циализировать.
И н и ц и а л и з а ц и я константного указателя может быть выполнена тре
мя способами:
• определением адреса глобальной переменной с использованием
оператора @;
• указанием адреса, равного n i l ;
• заданием значения константы типа PChar или PWideChar.
Например:
const P I : " I n t e g e r =
{ i 1 - переменная типа Integer}
const StrNew: PChar = 'NewConst';
const PFunc: P o i n t e r = @MyFunc;
57
Курс
Введение в программирование
Типы данных языка JAVA
Java — это я з ы к со строгой типизацией. Это означает, что т и п ы д а н
ных д о л ж н ы быть определены уже на этапе к о м п и л я ц и и .
Все т и п ы данных в Java м о ж н о подразделить на две группы:
• простые т и п ы ;
• ссылочные типы.
Я з ы к Java позволяет использовать следующие простые типы:
• числовые т и п ы
— целые типы:
byte (8-битовое значение)
диапазон значений от -128 до 127
short (16-битовое значение) диапазон значений от -32768
до 32767.
int (32-битовое значение)
диапазон значений от -2147483648
до 2147483647
long (64-битовое значение)
диапазон значений
от -9223372036854775808
до 9223372036854775807
• т и п ы значений с плавающей точкой:
float (32-битовое значение)
double (64-битовое значение)
• символьный тип
char (16-битовое значение Unicode)
• логический тип
boolean (значение true или false)
Например:
// Объявление переменных
boolean b1=true;
float
fN1=74.3F;
f l o a t fN2=(float)(fN1+2);
double dN1=14573.74;
double dN2= 81.2E-2;
Значение одного целого типа может быть приведено к значению дру¬
гого целого типа.
Приведение целых типов к логическому и обратно выполнять нельзя.
Я з ы к Java предусматривает для целочисленных значений следующие
операторы:
• операторы сравнения
=
равно
!=
н е равно
58
Лекция 6
• операторы отношения
<
<=
>
>=
• унарные операторы
+
Простые типы данных
меньше
меньше или равно
больше
больше или равно
положительное значение
отрицательное значение
• бинарные операторы
+и + =
сложение
(x=x+y эквивалентно записи x+=y)
-и - =
вычитание
(x=x-y эквивалентно записи x-=y)
*и * =
умножение
(x=x*y эквивалентно записи x*=y)
/и / =
деление
(x=x/y эквивалентно записи x/=y)
%и % =
остаток от деления
• п р е ф и к с н ы й и п о с т ф и к с н ы й оператор п р и р а щ е н и я и декремента
++
приращение
(увеличение значения на 1
до вычисления выражения (++х)
или после (х++))
декремент
операторы сдвига
<<
сдвиг влево
>>
сдвиг вправо с распространением
знака
>>>
сдвиг вправо без учета знака
(слева происходит заполнение
нулями)
• унарный логический оператор
~
отрицание (побитовое
дополнение)
• бинарные логические операторы
&
логическое И ( A N D )
I
логическое И Л И (OR)
"
логическое исключающее И Л И (XOR)
Если оба операнда имеют целочисленный тип, то операция рассма
тривается как целочисленная. Если один из операндов имеет тип long, то
операция выполняется с использованием 64-битового представления:
при этом любой другой операнд будет расширен до типа long и результат
59
Курс
Введение в программирование
будет также иметь тип long. В противном случае операции выполняются,
используя 32-битовое представление (любой операнд, не я в л я ю щ и й с я i n t ,
первоначально расширяется до типа i n t ) и результат будет иметь тип i n t .
Логические значения представляются одним битом и обозначаются
константами true и false.
В я з ы к е Java нельзя прямо выполнить приведение типа i n t к типу
boolean, н о м о ж н о конвертировать значение i n t , используя следующий
синтаксис языка: i n t x != 0, где любое ненулевое значение х даст в р е
зультате t rue, а нулевое значение даст f a l s e . Д л я преобразования значения
типа boolean в целое следует выполнить условный оператор: bool x ? 1:0.
Для логических значений в я з ы к е Java предусмотрены следующие
операторы:
J == и ! =
J !, &, |, и "
J && и ||.
Типы данных языка С#
В я з ы к е С # нет базовых типов — все т и п ы реализуются к а к классы
библиотеки N E T Framework. Однако я з ы к C# имеет набор встроенных
типов, которые рассматриваются к а к псевдонимы типов в пространстве
и м е н System. Н а п р и м е р , тип s t r i n g — это псевдоним типа System. S t r i n g , а
тип i n t — псевдоним типа System. Int32.
С # поддерживает следующие встроенные типы:
• bool — псевдоним класса System. Boolean;
• byte — псевдоним класса System. Byte;
• sbyte — псевдоним класса System.SByte;
• char — псевдоним класса System.Char;
• decimal — псевдоним класса System. Decimal;
• double — псевдоним класса System. Double;
• float — псевдоним класса System.Single
• int — псевдоним класса System. Int32;
• uint — псевдоним класса System. UInt32;
• long — псевдоним класса System. Int64;
• ulong — псевдоним класса System. UInt64;
• object — псевдоним класса System.Object;
• short — псевдоним класса System. Int16;
• ushort — псевдоним класса System. UInt16;
• string — псевдоним класса System.String.
Все встроенные т и п ы подразделены на группы:
• целочисленные т и п ы ( i n t , long, ulong);
• вещественные т и п ы ( f l o a t , double);
60
Лекция 6
Простые типы данных
• логический тип (bool);
• символьные т и п ы (char, s t r i n g ) ;
• объектный тип (object).
Иерархия классов N E T Framework имеет один о б щ и й корень — класс
System. Object.
Все т и п ы разделяются на две категории:
• размерные типы;
• ссылочные типы.
П р и создании переменной размерного типа под нее в стеке выделя
ется определенный объем памяти, соответствующий типу этой перемен
ной. П р и передаче такой переменной в качестве параметра выполняется
передача значения, а н е ссылки на него. Значение размерного типа н е м о
жет быть равным n u l l . К размерным типам относятся целочисленные и
вещественные т и п ы , структуры, перечислимые типы.
При создании переменной ссылочного типа память под созданный объ
ект выделяется в куче. Ссылка всегда указывает на объект заданного типа.
В я з ы к е C# все массивы являются объектами. Базовым классом мас
сива является класс Array пространства и м е н Systems.
Я з ы к C# позволяет создавать следующие массивы:
• одномерные массивы;
• многомерные массивы;
• н е в ы р о в н е н н ы е массивы.
Массивы относятся к ссылочным типам.
Одномерный массив м о ж н о создать одним и з следующих способов:
• отдельно объявить массив без указания размерности. Например:
i n t [ ] myArr1;
• создать уже объявленный массив с одновременной его инициализа¬
цией. Например:
myArr1 = new i n t [ ] {1, 2, 3, 4};
• отдельно объявить массив с указанием размерности и соответствен¬
но созданием объекта. Например:
i n t [ ] myArr2 = new i n t [ 4 ] ;
• объявить массив с одновременной его инициализацией (с указанием
оператора new). Например:
i n t [ ] myArr3 = new i n t [ ] {1, 2, 3, 4};
s t r i n g [ ] s C o l o r = new s t r i n g [ ] {"Yellow","Blue","Red"};
• объявить массив с одновременной его инициализацией (короткая
форма). Например:
i n t [ ] myArr4 = {1, 2, 3, 4};
Отметим, что нельзя выполнять и н и ц и а л и з а ц и ю массива в форме
myArray5 = {1, 2}; для предварительно объявленного или уже созданного
массива.
61
Курс
Введение в программирование
П р и создании многомерных массивов их размерность определяется
числом запятых плюс один, указанных в квадратных скобках после типа
массива. Ф о р м ы создания многомерного массива аналогичны ф о р м а м
создания одномерного массива.
Например:
i n t [ , ] i A r r 1 = new i n t [ 8 , 2 ] ;
Невыровненный массив реализуется к а к массив массивов.
Н а п р и м е р , массив и з трех элементов, каждый и з которых содержит
двумерный массив, может быть описан следующим образом:
i n t [ ] [ , ] iJaggedArr1 = new i n t [ 3 ] [ , ]
{ new i n t [ , ] { {1,1}, {8,8} },
// первый элемент массива
new i n t [ , ] { {5,5}, {6,6}, {7,7} }, // второй элемент массива
new i n t [ , ] { {0,0}, {0,0}, {0,0} }
// третий элемент массива
};
Операторы new д о л ж н ы использоваться для создания каждого мас
сива: первое вхождение оператора new создает одномерный массив, каж
д ы й из трех элементов которого также является массивом, а три следую
щих вхождения оператора new создают элементы к а к двумерные массивы.
В обычных массивах индексы элементов представляют собой подряд
идущие целочисленные значения. Библиотека N E T Framework предо
ставляет класс Collections.Hashtable, позволяющий создавать х э ш и р о в а н н ы е массивы.
Например:
C o l l e c t i o n s . H a s h t a b l e hArr = new C o l l e c t i o n s . H a s h t a b l e ( ) ;
h A r r [ " i " ] = 175; // Значение индекса указывается типом s t r i n g
Представление целочисленных и вещественных типов данных
Представление целочисленных и вещественных значений в памяти
компьютера в большинстве случаев реализуется аппаратным способом с
учетом возможностей конкретного процессора. Также аппаратно реализу
ется п р и м и т и в н ы й набор операций над этими значениями. П р и м е н е н и е
операций, реализуемых аппаратно, значительно более э ф ф е к т и в н о , чем
использование программно реализуемых операций. Поэтому к о м п и л я т о
р ы по возможности формируют код, в котором применяется аппаратная
реализация примитивных операций (таких, к а к сложение, вычитание,
умножение и деление).
62
Лекция 6
Простые типы данных
Целочисленное значение типа i n t e g e r , записанное к а к «signed 32b i t * , может иметь в памяти компьютера следующее представление:
Ячейка памяти (4 байта):
Знаковый
бит числа
Биты 31 — 0
1
1
0
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
Целочисленное значение типа s h o r t i n t , записанное как «signed 8-bit»,
может иметь в памяти компьютера следующее представление:
1 байт я ч е й к и памяти:
Знаковый
бит числа
Биты 7 — 0
1
1
0
1
1
1
1
1
1
1
Максимально допустимое значение, которое можно записать в 7 бит —
это восьмеричное число 177, которое в десятичном исчислении равно 127
(177 =1*8 +7*8 +7*8 =127 ).
2
8
1
0
10
Таким образом, диапазон допустимых значений для каждого цело
численного типа данных определяется к а к стандартом я з ы к а , так и воз
можностями аппаратуры.
В некоторых языках программирования представление целочислен
ного значения включает еще и хранение дескриптора этого значения. П р и
этом дескриптор может храниться к а к в одной ячейке со значением, так и
в различных ячейках. В первом случае наличие дескриптора значительно
уменьшает диапазон допустимых значений, а также, к а к правило, замед¬
ляет процесс выполнения арифметических операций (операции над ч а с
тью я ч е й к и памяти н е поддерживаются аппаратно).
П р и хранении дескриптора и значения в разных ячейках (этот с п о
соб представления используется для языка LISP) одновременно с дес
криптором хранится и указатель физического расположения значения.
Вещественные т и п ы аппаратно могут иметь два представления: ве¬
щественные числа с ф и к с и р о в а н н о й точкой и вещественные числа с пла¬
вающей точкой. К а к правило, по умолчанию компиляторы преобразуют
вещественные значения в э к с п о н е н ц и а л ь н ы й формат (формат с плаваю63
Курс
Введение в программирование
щей точкой), если синтаксис я з ы к а я в н о н е указывает п р и м е н е н и е фор¬
мата с ф и к с и р о в а н н о й точкой.
Вещественное значение с плавающей точкой может иметь в памяти
компьютера следующее представление:
Знаковый
бит числа
Экспонента
(8 разрядов)
Мантисса (23 разряда)
1
1
1
1
1
1 1 1 1 1
Для представления вещественных чисел с плавающей точкой и ве¬
щественных чисел двойной точности с плавающей точкой стандартом
I E E E 754 определены 32- и 64-битовые представления соответственно.
В разряды мантиссы записываются значащие ц и ф р ы , а в разряды
экспоненты заносится показатель степени. Положительные значения с о
держат в знаковом бите числа — 0, а отрицательные значения — 1.
П р и обозначении чисел с плавающей точкой п р и н я т ы следующие
соглашения: знаковый разряд обозначается буквой s, экспонента — e, а
мантисса — m.
В я з ы к е Java значения с плавающей точкой могут объявляться следу¬
ю щ и м и базовыми типами:
• float
диапазон значений от +3.40282347E+28
до +1.40239846E-45 (32 бита)
• double диапазон значений от +1.79769313486231579E+308
до +4.9406545841246544E-324(64 бита).
П о л н о й ненулевой ф о р м о й значения типа f l o a t является форма
s-m-2e, где s — это +1 или -1 (знаковый бит числа), m является положитель
н ы м значением, м е н ь ш и м , ч е м 2 24 (мантисса), и e является целым в пре
делах от -149 до 104 включительно (экспонента).
П о л н о й ненулевой ф о р м о й значения типа double является форма
s-m-2e, где s это +1 или -1, m является положительным значением, м е н ь
ш и м , ч е м 2 53, и e является целым в пределах от -1045 д о 1000 включи¬
тельно.
Положительным нулевым значением и отрицательным нулевым
значением являются 0.0 и -0.0 (0.0 == -0.0 дает в результате true), н о н е
которые операторы различают эти «эквивалентные» значения, например,
1.0/0.0 равно положительной бесконечности, а 1.01/-0.0 — отрицатель¬
ной бесконечности.
В я з ы к е Java п р и н я т ы следующие правила приведения веществен¬
ных типов:
А
А
64
Лекция 6
Простые типы данных
• любые значения любого типа с плавающей точкой могут быть п р и
ведены к любому другому значению числового типа;
• любые значения любого типа с плавающей точкой могут быть п р и
ведены к значению типа char и наоборот;
• приведение невозможно между значениями типа boolean и значени
я м и с плавающей точкой.
Если оба операнда имеют тип f l o a t , или один имеет тип f l o a t , а дру¬
гой — целый тип, то результат будет иметь тип f l o a t .
Если ж е хотя бы один из операндов имеет тип double (устанавливае
м ы й по умолчанию), то другой операнд также приводится к типу double и
результат будет иметь тип double.
Операции со значениями с плавающей точкой не выдают исключений.
П р и вычислениях значений с плавающей точкой следует учитывать
правила округления. Так например, для значений с плавающей точкой
выражение 1,0*10 не равно значению 10. Это иллюстрирует следующий
пример на я з ы к е Java:
p u b l i c c l a s s MyFloatSumma
{ public s t a t i c void main(String[]
args)
{
f l o a t f1 = ( f l o a t ) 1.0; // Число с плавающей точкой
f l o a t fSum = 0; // Переменная для записи результата
f i n a l s t a t i c f l o a t myDeltaFloat = ( f l o a t ) 0.00001; // Дельта
// для "усечения" мусора мантиссы
// Способ вычисления - простое суммирование и сравнение
f o r (byte i=0; i<10;
fSum = fSum + ( f l o a t ) 0.1;
// Цикл от 0 до 10
i f ( f 1 == fSum) // Сравнение ( f l o a t ) 1.0 и полученной суммы
S y s t e m . o u t . p r i n t l n ( " Числа равны");
else
S y s t e m . o u t . p r i n t l n ( " Числа различны");
// Правильный способ вычисления - с "усечением" мусора мантиссы
fSum = 0;
f o r (byte i=0; i<10; i++) fSum = fSum + ( f l o a t ) 0.1;
i f (Math.abs(fSum - f 2 ) < myDeltaFloat)
System.out. p r i n t l n ( " Числа одинаковы");
else
System.out. p r i n t l n ( " Числа различны");
}
}
65
Курс
Введение в программирование
Л е к ц и я 7. П р о и з в о д н ы е т и п ы д а н н ы х я з ы к а С + + .
Массивы и указатели
Производные типы
Производные т и п ы м о ж н о условно подразделить на две группы:
Непосредственно производные типы. Эти т и п ы являются производ
н ы м и от некоторых существующих типов, реализуя т и п ы указателей,
ссылки, ф у н к ц и и преобразования типов. В группу непосредственно п р о
изводных типов входят:
• массивы;
•
указатели;
• ссылки;
• перечисления;
• указатели на члены класса.
- Составные производные типы. В группу составных производных т и
пов входят:
• классы;
•
структуры;
• объединения;
Массивы
Объявление массивов
Массив переменных или объектов состоит из определенного числа
однотипных данных, называемых элементами массива. Все элементы мас
сива индексируются последовательно, начиная с нуля.
Размещение элементов массива в памяти выполняется последова¬
тельно.
Количество элементов в массиве определяет размер массива и я в л я
ется константным выражением. Для создания динамических массивов
стандартная библиотека C++ предусматривает тип vector.
И м я массива, определяет адрес первого элемента массива.
И м я массива в отличие от и м е н и вектора, нельзя указывать в левой
части оператора присваивания.
Объявление массива может иметь следующее формальное описание:
// Объявление одномерного массива
тип имя_массива[размерност^];
66
Лекция 7
Производные типы данных языка С++. Массивы и указатели
// Объявление одномерного массива с одновременной инициализацией
тип имя_массива[размерност^] =
{значение0, значение1
значение_N};
// Объявление безразмерного массива с одновременной инициализацией:
// размерность определяется количеством значений, указанных
//в списке инициализации
тип имя_массива[]={значение0, значение1
значение_N};
// Объ вление многомерного массива
тип имя_массива[размерность_^]... [размерность_MN];
// Объявление многомерного массива с одновременной инициализацией
тип имя_массива[размерность_N]... [размерность_M] =
{ {значение0, значение1
значение_M}, ...
{значение0^ значение1N
значение_NM}};
Размерность массива может:
• указываться л ю б ы м константным выражением целого типа;
• автоматически определяться к о м п и л я т о р о м по списку значений
и н и ц и а л и з а ц и и массива (если размерность не указана я в н о ) .
Например:
i n t arrayOfInteger[17];
// Массив из 17 переменных
// типа i n t
char arrayOfChar_3[3]={'L','M','N'};
// Объявление и
// инициализаци символьного массива
char arrayOfChar_0[] = {"Array of char. \n"};
i n t arrayOfInteger_6[2][3]=
{{1,2,3}, {11,12,13}};
// Объявление и
// инициализаци двумерного массива
Если н и размерность массива, н и с п и с о к значений и н и ц и а л и з а ц и и
не указаны, то будет создан массив нулевой д л и н ы .
Объявление многомерных массивов выполняется по следующим
правилам:
• список значений инициализации можно указывать как в единых фигур
ных скобках, так и в общих фигурных скобках, включающих через запя¬
тую списки по каждому левому индексу в отдельных фигурных скобках;
• при использовании общих фигурных скобок сначала следует указы¬
вать значения для неизменяемого самого левого индекса;
• м о ж н о не указывать только самую левую размерность массива, полу¬
чая ее значение из списка значений инициализации.
И н и ц и а л и з а ц и ю массива м о ж н о выполнить одним из следующих
способов:
67
Курс
Введение в программирование
• указать во время объявления массива в фигурных скобках значения
и н и ц и а л и з а ц и и (начиная с нулевого элемента и первого столбца);
• присвоить значение элементам массива во время в ы п о л н е н и я про¬
граммы;
• объявить массив к а к глобальный или статический, инициализируе
м ы й по умолчанию (для числовых значений выполняется и н и ц и а л и
зация нулями, а для указателей — значением n u l l ) . Глобальный мас
сив объявляется вне всех ф у н к ц и й , а статический массив объявляет
ся с модификатором s t a t i c .
Если количество значений и н и ц и а л и з а ц и и больше, ч е м объявлен
ная размерность массива, то компилятор Visual C++ инициирует ошибку.
Если количество значений и н и ц и а л и з а ц и и меньше, ч е м объявлен
ная размерность массива, то оставшиеся значения автоматически и н и ц и
ализируются нулями.
Размещение массива в памяти
При создании массива память под все его элементы выделяется после
довательно для каждого элемента в зависимости от типа массива. Для много
мерных массивов в первую очередь изменяются значения самого правого ин¬
декса.
Например, для массива char aCh[2][4] будет выделено восемь байтов па
мяти, в которых в следующем порядке будут размещены элементы массива:
Элемент
aCh
[0][0]
aCh
[0][1]
aCh
[0][2]
aCh
[0][3]
aCh
[1][0]
aCh
aCh
[1][2]
aCh
[1][3]
N байта
1
2
3
4
5
6
7
8
Двухмерные массивы м о ж н о рассматривать к а к матрицу, в которой
первый индекс определяет строку, а второй индекс — столбец. П о р я д о к
расположения элементов матрицы в памяти — по строкам.
П р и размещении трехмерного массива char aCh[3][2][5] память под
элементы этого массива будет выделяться последовательно в соответст
вии со следующими значениями индексов:
000
001
002
003
004
010
011
00102
00113
01042
103
104
110
111
112
113
114
200
201
202
203
204
210
211
212
213
214
68
Лекция 7
Производные типы данных языка С++. Массивы и указатели
О б щ и й объем выделяемой под массив памяти определяется как про¬
изведение всех размерностей массива (общее число элементов), умно¬
ж е н н о е на длину типа данных массива.
Элементы массива
Доступ к элементам массива может выполняться:
• по указателю на массив и индексу элемента, задаваемого в квадрат¬
ных скобках: первый элемент массива имеет индекс 0;
• по указателю на элемент массива.
Для получения адреса элемента массива применяется оператор &.
И м я массива является адресом массива и эквивалентно следующему
выражению: &имя_массива[0].
Для определения размерности массива в байтах м о ж н о использовать
функцию sizeof^Mfl_Mac^Ba).
Например:
arrayOfInteger[0]=1;
// Присваивание значения
// первому элементу массива
iInt1=arrayOfInteger[1]=13;
// Групповое присваивание
iInt2=&arrayOfInteger[4];
// Получение адреса пятого
//элемента массива
Символьные массивы и строки
Синтаксис я з ы к а не имеет простого строкового типа (стандартная
библиотека содержит тип s t r i n g , но переменные данного типа не являют
ся массивами символов). Поэтому для работы со строками удобно и с
пользовать массивы символов. Объявить массив символов — строку —
м о ж н о двумя способами:
• указать посимвольно каждый элемент массива, включая символ
конца строки;
• указать в двойных кавычках при и н и ц и а л и з а ц и и массива значение
строки (символ конца строки будет добавлен автоматически).
Символом конца строки служит null-символ \0. При подсчете числа сим
волов в строке учитывается общее число символов плюс символ конца строки.
Например:
char
arrayOfChar[6];
arrayOfChar[0]='A';
// Доступ через указатель на массив и индекс
char * ph = arrayOfChar;
// Создание указателя на элемент массива
ph++;
// Переход к следующему элементу массива
69
Курс
Введение в программирование
П р е ф и к с н ы й оператор * называется оператором разыменования.
Если ph указывает на элемент массива, то *ph является значением этого
элемента.
Любое выражение, имеющее тип массива, может быть преобразова¬
но к указателю того ж е типа: результатом будет указатель на первый эле¬
мент массива.
Например:
char cStr[_MAX_PATH];
// Массив типа char
char *pStr = c S t r ;
// Указатель на массив:
// эквивалентно выражению & c S t r [ 0 ]
Указатели
Указатели на переменные
Указатель на переменную содержит адрес памяти расположения
этой переменной.
Объявление указателя имеет следующее формальное описание:
тип_переменной *имя_переменной_адреса;
И н и ц и а л и з а ц и я указателя выполняется следующим образом:
тип_переменной имя_переменной_содержания;
имя_переменной_адреса= &имя_переменной_содержания;
Объявление указателя может быть выполнено
инициализацией:
тип_переменной
с одновременной
*имя_переменной_адреса=&имя_переменной_содержания;
Доступ к значению переменной по указателю имеет следующее фор¬
мальное описание:
имя_переменной_содержания1=*имя_переменной_адреса;
•
•
•
•
•
П р и работе с указателями действуют следующие правила:
при объявлении переменной-указателя перед именем переменной
указывается операция *;
если одним оператором объявляется несколько переменных-указате
лей, то перед каждой такой переменной следует указывать операцию *;
после объявления указателя его следует инициализировать адресом
значения того ж е типа, что и тип указателя;
для получения адреса переменной перед ее именем указывается опе
рация взятия адреса &;
для получения значения переменной по указателю на нее перед ука
зателем ставится операция разыменования * (называемая иногда
операцией взятия значения);
70
Лекция 7
Производные типы данных языка С++. Массивы и указатели
• указатель строки содержит адрес первого символа строки;
• при увеличении указателя на единицу значение, содержащееся в п е
ременной-указателе, увеличивается на число байт, которое отведено
под переменную данного типа.
Операцию взятия адреса & нельзя использовать:
• для регистровых переменных ( r e g i s t e r r1; pReg=&r1; ) ;
• с константами (pAdr1=&444; ) ;
• с арифметическими в ы р а ж е н и я м и ( i n t i= 1234; pAdr1=&(i+3)).
Например:
i n t iVar;
i n t * pInt;
// Указатель
pInt=&iVar; // Эквивалентно оператору i n t *pInt=&iVar;
*pInt=20;
// Эквивалентно оператору iVar=20;
char* pStr="The s t r i n g " ;
iVar=strlen(pStr);
// Определение длины строки
Указателю может быть присвоено значение другого указателя: в этом
случае следует использовать операцию *. Компилятор Visual C++ отсле
живает некорректные присваивания — указателю значения и л и наоборот,
и выдает предупреждение о различных уровнях адресации.
На следующей схеме иллюстрируется соотношение указателя и зна
чения.
Переменные
char A
Объявление
char B
и инициализация
2000
Адреса ячеек памяти
2001
Указатели
char
char
*pA
*pB
3000
3020
Содержание ячеек:
Операции:
A='w';
pA= &A;
B=*pA;
2000
/ / адрес переменной A
/ / з н а ч е н и е переменной A
W
*pA=' я / / изменение значения
pB=pA;
/ / а д р е с переменной A
2000
pB=&A;
/ / а д р е с переменной A
2000
71
Курс
Введение в программирование
Операции инкремента ++ и декремента
указателя м о ж н о в ы п о л
нять к а к после операции присвоения (*pV++=22;), так и д о нее (*++pV=22;).
В последнем случае сначала будет увеличено значение указателя, а затем
в ы п о л н е н оператор присваивания.
Выполнять вычитание м о ж н о только над указателями одного типа.
Результатом вычитания указателей является целое ч и с л о , указывающее
разность адресов памяти.
Над указателями одного типа м о ж н о выполнять операцию сравне
н и я , возвращающую логическое значение.
Так ж е к а к и при работе с массивами, компилятор Visual C++ н е в ы
полняет для указателей проверку на предельные значения.
Константные указатели
Значение указателя на константу м о ж н о изменять, а значение к о н
стантного указателя является константой и н е подлежит и з м е н е н и ю .
Например:
char str1[]="123";
const char* pstr1= s t r 1 ; // pstr1 можно изменять,
// а *pstr1 — нельзя.
Задание ключевого слова const перед объявлением указателя создает
этот указатель к а к указатель на константу (при этом само значение, до¬
ступное н е через д а н н ы й указатель, остается изменяемым).
Д л я того чтобы создать константный указатель, вместо оператора *
используется * const.
Например:
const char *const pstr1= s t r 1 ;
Указатели на массивы
И указатель, и массив содержат адрес. Поэтому указателю может
быть присвоен адрес первого элемента массива или и м я массива. Н о ад
ресу массива нельзя присвоить значение указателя.
Например:
float fArray[3];
// Массив
f l o a t * pArray;
pArray=fArray; // Эквивалентно оператору pArray=&fArray[0];
pArray++;
// Указывает на второй элемент массива
72
Лекция 7
float*
Производные типы данных языка С++. Массивы и указатели
pArray2;
pArray2=&fArray[1];
// Указывает на второй элемент массива
Указатели на указатели
Объявление указателя на указатель имеет следующее формальное
описание:
тип **имя_указателя_на_указатель;
П р и объявлении указателя на указатели уровнем вложенности ука¬
зателей служит число звездочек перед именем переменной.
Для получения значения по указателю на указатели перед именем
указателя надо записать количество звездочек, равное уровню вложенно
сти указателя.
Например:
i n t i V , jV;
i n t * pV=&iV;
// pV — это адрес, а *pV — значение
i n t * * ppV=&pV;
i n t * * * pppV=&ppV;
iV=77;
// Эквивалентно **ppV=77;
jV=*pV; // Эквивалентно jV=**ppV; или jV=***pppV;
Ссылки
Ссылка вводит д л я доступа к п е р е м е н н о й второе и м я и является
к о н с т а н т н ы м указателем н а объект. З н а ч е н и е п е р е м е н н о й - с с ы л к и и з м е
н и т ь нельзя. П р и о б ъ я в л е н и и с с ы л к и перед и м е н е м п е р е м е н н о й ставит
ся символ &. С с ы л к а п р и о б ъ я в л е н и и всегда д о л ж н а быть п р о и н и ц и а л и зирована.
Например:
i n t iV=12;
i n t &sV=iV;
// sV - ссылка
cout<< sV;
// sV равно 12
sV=22;
// значение i V стало равно 22
sV++;
// sV и i V стало равно 23
i n t *pV= &sV;
// указатель на sV и i V
Преобразование типа для указателей
Преобразование типа указателя происходит п р и различных опера
циях, таких к а к вызов процедуры, присваивание, и н и ц и а л и з а ц и я и т.п.
73
Курс
Введение в программирование
Указатель типа void может быть преобразован к указателю любого
другого типа только я в н ы м приведением типа. Н о указатель любого типа
может быть н е я в н о преобразован к указателю типа void.
Это применяется для передачи параметров ф у н к ц и и , если тип фор¬
мального параметра не очевиден (он может быть указателем типа i n t *
или типа f l o a t *). В этом случае в прототипе ф у н к ц и и вместо явного за
дания типа записывается тип void.
Например:
Fx(void *px); // Прототип функции
Fx(pi);
// Вызов функции для i n t * p i
Fx(pf);
// Вызов функции для f l o a t * pf
В теле ф у н к ц и и для работы с указателем следует использовать я в н о е
преобразование типа.
Например:
( i nt *)px.
Типы, определяемые в пространствах имен
Пространство имен позволяет именовать группу переменных и методов.
Создание пространства имен указывается ключевым словом namespace.
Пример:
namespace X
{
int i ;
v o i d main()
{
S::i++;
// Пространство имен Х
}
// Обращение к переменной i из пространства имен S
}
В я з ы к е С + + объявляемые пространства и м е н могут быть иерархи¬
чески вложены друг в друга.
Например:
namespace Outer { i n t iOuter1= 111;
i n t func(int j ) ;
namespace Inner
{
i n t i I n n e r 1 = 222;
}
}
Для традиционных приложений можно использовать стандартную
библиотеку С + + , которая определяет дополнительный набор типов. Прост
ранство имен стандартной библиотеки обозначается идентификатором std.
74
Лекция 7
Производные типы данных языка С++. Массивы и указатели
Для того чтобы иметь возможность обращаться к переменным или
методам из пространства и м е н , м о ж н о использовать один из следующих
способов:
• имя соответствующей переменной или метода должно быть квали¬
ф и ц и р о в а н о названием пространства имен (пространство и м е н ука¬
зывается перед именем через два символа двоеточия).
Например:
s t d : : s t r i n g S='^TO строка";
• имя библиотеки должно быть установлено как доступное операто¬
ром using. Например:
using namespace s t d ;
// ...
s t r i n g s1 = "Строкa s1";
Оператор using м о ж н о указывать как до метода main, так и внутри ме¬
тода main (в этом случае переменные и методы пространства и м е н будут
доступны без к в а л и ф и к а ц и и их и м е н и сразу после выполнения операто¬
ра using).
Для управляемых р а с ш и р е н и й используются библиотеки среды N E T
Framework, реализованные как пространства имен. Пространство и м е н
System предоставляет большой набор типов, реализованных как классы
или структуры.
75
Курс
Введение в программирование
Л е к ц и я 8. П р о и з в о д н ы е т и п ы д а н н ы х я з ы к а С + + .
Структуры, объединения и перечисления
Структуры
Объявление структуры
Структуры я з ы к а C++ представляют поименованную совокупность
компонентов, называемых полями, или элементами структуры. Элемен¬
том структуры может быть:
• переменная любого допустимого типа;
• битовое поле;
• функция.
Объявление структуры имеет следующее формальное описание:
s t r u c t [имя_структуры] {
тип_элемента_структуры
тип_элемента_структуры
имя_ элемента1;
имя_ элемента2;
тип_элемента_структуры
имя_ элементам;
} [список_объявляемых_переменных];
Объявление структуры с битовыми полями имеет следующее фор¬
мальное описание:
s t r u c t [имя_структуры] {
тип_элемента_структуры
тип_элемента_структуры
[имя_ элемента1] : число_бит;
[имя_ элемента2] : число_бит;
тип_элемента_структуры
[имя_ элементам] : число_бит;
} [список_объявляемых_переменных];
Возможно неполное объявление структуры, имеющее следующее
формальное описание:
s t r u c t имя_структуры;
П р и отсутствии и м е н и объявляемой структуры создается а н о н и м н а я
структура. П р и создании а н о н и м н о й структуры обычно указывается с п и
сок объявляемых переменных.
76
Производные типы данных языка С++.
Структуры, объединения и перечисления
Лекция 8
С п и с о к объявляемых переменных типа д а н н о й структуры может со¬
держать:
• имена переменных;
• имена массивов;
• указатели.
Например:
s t r u c t sA {char a [ 2 ] , i n t i ; } struA, s t r u B [ 1 0 ] ,
*struC;
Для использования указателя на структуру ему необходимо присво¬
ить адрес переменной типа структуры.
Размер структуры с битовыми полями всегда кратен байту. Битовые
п о л я м о ж н о определять для ц е л о ч и с л е н н ы х п е р е м е н н ы х т и п а i n t ,
uns i gned i nt , char и uns i gned char . Одна структура одновременно может
содержать и переменные, и битовые поля. Если для битового поля не за
дано и м я элемента, то доступ к такому полю не разрешен, но количество
указанных бит в структуре размещается.
Типом элемента структуры может быть:
• другой структурный тип (допускаются вложенные структуры);
• указатель на д а н н ы й структурный тип;
• неполно объявленный структурный тип;
• любой другой базовый или производный тип, не ссылающийся ре
курсивно на объявляемый структурный тип.
Например:
s t r u c t sA {char a [ 2 ] , sA* t h i s _ s t r u c t ; } ;
// Корректное
// объявление структуры
s t r u c t sB;
// Неполное объявление структуры
s t r u c t sA {char a [ 2 ] , sB s b * _ s t r u c t ; } ;
// Корректное объявление
// структуры
s t r u c t sA {char a [ 2 ] , sA t h i s _ s t r u c t ; } ; // Ошибочное объявление
Структура не может содержать в качестве вложенной структуры саму
себя, но она может содержать элемент, я в л я ю щ и й с я указателем на объяв
ляемую структуру.
Например:
struct structA
{ struct structA
*pA; i n t i A ; } sA; // pA указа¬
// тель на структуру
П р и одновременном объявлении структурного типа, объявлении пе¬
ременной данного типа и ее и н и ц и а л и з а ц и и список значений указывает77
Курс
Введение в программирование
ся в фигурных скобках в последовательности, соответствующей последо
вательности определения элементов структуры.
Например:
s t r u c t POINT
// Объявление структурного типа POINT
{
i n t x;
// Объявление элементов x и y
i n t y;
} p_screen = { 50, 100 }; // Эквивалентно записи p_screen.x = 50;
// и p_screen.y = 100ж
Массив структурного типа создается как обычный массив, указанием в
квадратных скобках справа от имени переменной числа элементов массива.
Выделение памяти
П р и создании переменной типа структуры:
• память под все элементы структуры выделяется последовательно для
каждого элемента;
• для битовых полей память выделяется, начиная с младших разрядов;
• память, выделяемая под битовые поля, кратна байту;
• общая выделяемая память может быть больше, чем сумма размеров
полей структуры.
Рассмотрим пример выделения памяти под структуру
struct structA {
char cA;
char sA[2];
f l o a t fA;};
П р и создании переменной структурного типа:
s t r u c t A s1;
будет выделено 7 байтов. Элементы структуры будут р а з м е щ е н ы в
памяти в следующем порядке:
char c A
1
char sA[2]
2
float fA
3
4
5
6
Рассмотрим пример выделения памяти под структуру
78
7
Производные типы данных языка С++.
Структуры, объединения и перечисления
Лекция 8
struct structB {
int i1:2;
int i2:3;
i n t :6;
unsigned i n t i 3 : 4 ; } ;
П р и создании переменной структурного типа:
s t r u c t B s2;
будет выделено 2 байта. Элементы структуры будут р а з м е щ е н ы в па¬
мяти в следующем порядке:
i3
Биты
15 14
не доступны
13 12
11 10
9
8
7
i2
6
5
4
i1
3
2
1
0
Для целочисленных значений, предусматривающих наличие з н а к о
вого разряда (например, i n t ) , старший левый бит из общего числа битов,
выделяемых под д а н н о е битовое поле, интерпретируется к а к знак. Н а
пример, битовое значение 11 для поля i 1 будет восприниматься как —1, а
значение 11 для поля i 3 — как 3.
Доступ к элементам структуры
Элементы структуры могут иметь модификаторы доступа: p u b l i c ,
p r i v a t e и protected. П о умолчанию все элементы структуры объявляются
как общедоступные ( p u b l i c ) . Забегая вперед, следует сказать, что все чле
н ы класса по умолчанию объявляются как з а щ и щ е н н ы е ( p r i v a t e ) .
Для обращения к отдельным элементам структуры используются
операторы: . и ->.
Доступ к элементам структуры может иметь следующее формальное
описание:
переменная_структурного_типа.элемент_структуры=значение;
имя_структурного_типа *указатель_структуры=
& переменная_структурного_типа;
указатель_структуры->элемент_структуры=значение;
Например:
struct structA {
char c1;
char s1[4];
79
Курс
Введение в программирование
f l o a t f1;} aS1,
*prtaS1=&aS1;
struct structB {
// aS1 — переменная структурного типа
// prtaS1 — указатель на структуру aS1
// Вложенная структура
s t r u c t s t r u c t A aS2;
} bS1,*prtbS1=&bS1;
aS1.c1= 'Е'
// Доступ к элементу c1 структуры aS1
prtaS1->c1= 'Е'
// Доступ к элементу c1 через указатель prtaS1
(*prtaS1).c1= ' Е'
// Доступ к элементу c1
(prtbS1->aS2).c1='E' // Доступ к элементу вложенной структуры
Доступ к элементу массива структурного типа имеет следующий
формальный синтаксис:
имя_массива[индекс_элемента_массива].элемент_структуры .
П р и использовании указателей на массив структур следует сначала
присвоить указателю адрес первого элемента массива, а затем реализовывать доступ к элементам массива, изменяя этот указатель адреса.
Например:
s t r u c t s t r u c t A { i n t i ; char с;} sA[4], *psA;
*psA=&sA[0];
cout<<psA->i;
psA++;
cout<<psA->i;
// Доступ к первому элементу массива структур
// Переход ко второму элементу массива
// Эквивалентно записи: *psA=&sA[1];
Передача структур в качестве параметров
П е р е м е н н ы е структурного типа и элементы структуры м о ж н о пере¬
давать в ф у н к ц и и в качестве параметров.
Передача параметров может выполняться:
• по ссылке и л и указателю;
• по значению.
П р и передаче параметра по указателю передается только указатель
на структуру, при передаче по значению в стек копируется все содержание
структуры.
Например:
s t r u c t s t r u c t A { i n t i ; char c;} sA, *psA=&sA;
v o i d F 1 ( s t r u c t s t r u c t A sA);
// Передача параметров по значению
80
Производные типы данных языка С++.
Структуры, объединения и перечисления
Лекция 8
v o i d F 2 ( s t r u c t s t r u c t A *psA); // Передача параметров по указателю
v o i d F 3 ( s t r u c t s t r u c t A &sA); // Передача параметров по ссылке
v o i d F 2 ( s t r u c t s t r u c t A *psA) {
: psA->i =10; }
// Доступ к элементу структуры
П р и большой вложенности вызовов и использовании большого ч и с
ла структур или их значительных размерах вызов по значению может п р и
вести к переполнению стека.
Ф у н к ц и я может возвращать значение структурного типа или типа
указателя на структуру.
Например:
s t r u c t s t r u c t A { ¥nt ш; char с;};
s t r u c t structA Function3(void);
//
//
//
//
s t r u c t structA *Function4(void);
Функция возвращает значение
структурного типа
Функция возвращает указатель
на структуру
Объединения
Объединение позволяет размещать в одном месте памяти д а н н ы е ,
доступ к которым реализуется через переменные разных типов.
Использование объединений значительно э к о н о м и т память, выде
ляемую под объекты.
П р и создании переменной типа «объединение» память под все эле
менты объединения выделяется исходя из размера наибольшего его эле
мента. В каждый отдельный момент времени объединение используется
для доступа только к одному элементу данных, входящих в объединение.
Так, компилятор Visual C++ выделит 4 байта под следующее объединение:
union unionA {
char ch1;
f l o a t f1;} a1;
Элементы объединения
Количество занимаемых байтов
char c h l
1
float f l
1
81
2
3
4
Курс
Введение в программирование
Объединения, к а к и структуры, могут содержать битовые поля.
Инициализировать объединение при его объявлении м о ж н о только
заданием значения первого элемента объединения.
Например:
union unionA {
char ch1;
f l o a t f1;} a1={ 'M' };
Доступ к элементам объединения, аналогично доступу к элементам
структур, выполняется с п о м о щ ь ю операторов . и ->.
Например:
union TypeNum
{
int
i ;
long l ;
f l o a t f;
};
union TypeNum vNum = { 1 };
// Инициализация первого элемента
// объединения i = 1
cout<< vNum. i ;
vNum.f = 4.13;
cout<< vNum.f;
Элементы объединения н е могут иметь модификаторов доступа и
всегда реализуются к а к общедоступные ( p u b l i c ) .
Перечисления
Перечисление, или перечислимый тип определяет множество, состоя
щее из значений, указанных через запятую в фигурных скобках.
Перечисление задает для каждого мнемонического названия в ука¬
зываемом множестве свой индекс.
Перечисление может иметь следующее формальное описание:
enum имя_типа {список_значений} список_объявляемых_переменных;
enum имя_типа список_объявляемых_переменных;
enum ( список_элемент=значение);
Перечислимый тип описывает множество, состоящее из элементовконстант, иногда называемых нумераторами или именованными константами.
82
Производные типы данных языка С++.
Структуры, объединения и перечисления
Лекция 8
Значение каждого нумератора определяется к а к значение типа i n t .
П о умолчанию первый нумератор определяется значением 0, второй —
значением 1 и т.д. Д л я и н и ц и а л и з а ц и и значений нумератора н е с 0, а с
другого целочисленного значения, следует присвоить это значение перво¬
му элементу списка значений перечислимого типа.
Например:
// Создание перечисления
enum eDay{sn, mn, t s , wd, t h , f r , s t } day1;
// переменная day1 будет принимать значения
// в диапазоне от 0 до 6
day1=st;
// day1 - переменная перечислимого типа
i n t i1=sn;
// i 1 будет равно 0
day1= eDay(0);
// eDay(0) равно значению sn
enum(color1=255);
// Объявление перечисления, определяющего
// именованную целую константу c o l o r 1
int icolor=color1;
enum eDay2{sn=1, mn, t s , wd, t h , f r , s t } day2;
// переменна day2 будет принимать значени
// в диапазоне от 1 до 7
Для перечислимого типа существует понятие диапазона значений,
определяемого к а к диапазон целочисленных значений, которые может
принимать переменная данного перечислимого типа.
Для перечислимого типа м о ж н о создавать указатели.
83
Курс
Введение в программирование
Л е к ц и я 9. С т р у к т у р и р о в а н н ы е т и п ы д а н н ы х я з ы к а
O b j e c t Pascal
Объявление производного типа
К р о м е базовых типов данных, рассмотренных в л е к ц и и 6, я з ы к
Object Pascal предоставляет простые и структурированные т и п ы данных.
Используя базовые, простые и структурированные т и п ы данных,
м о ж н о создавать производные т и п ы данных.
Н а п о м н и м , что к базовым типам относятся:
• целочисленный тип;
• действительный тип;
• логический тип;
• символьный т и п ;
• строковый тип.
К простым типам относятся:
• порядковый тип;
• перечислимый тип.
К структурированным типам относятся:
• множества;
• массивы;
• записи;
• файлы;
• объектный тип (тип класса);
• тип ссылки на класс.
Для того чтобы создать переменную производного типа, сначала
следует определить этот производный тип. Объявление нового производ
ного типа указывается ключевым словом type.
Объявление произвольного типа к а к нового имени существующего
типа в я з ы к е Object Pascal имеет следующее формальное описание:
type имя_нового_типа = имя_существующего_типа;
Объявление произвольного типа к а к нового типа в я з ы к е Object
Pascal имеет следующее формальное описание:
type имя_нового_типа = type имя_существующего_типа;
П р и объявлении произвольного типа к а к нового и м е н и типа, тип
переменных производного типа и типа, используемого для его создания,
будет совпадать. Если перед именем существующего типа указать ключе84
Лекция 9
Структурированные типы данных языка Object Pascal
вое слово type, то компилятор создаст н о в ы й тип. П р и этом указание в ка¬
честве формального параметра подпрограммы переменной существую¬
щего типа, а в качестве фактического параметра подпрограммы — пере¬
м е н н о й нового типа, созданного на базе данного существующего типа,
вызовет для var-параметров ошибку времени к о м п и л я ц и и .
В я з ы к е Object Pascal объявление типов и переменных может быть
выполнено только в определенных местах программы: секция объявле
н и я типа type используется для объявлений типов, а секция var для объяв
л е н и я переменных.
Например:
type TValReal1 = Real;
var
X: Real; Y: TValReal1;
// Переменные X и Y имеют один и тот же тип
type TValReal2 = type Real;
var
X: Real;
Y: TValReal2; // Переменные X и Y имеют разные типы
Множества
Я з ы к Object Pascal предоставляет два простых типа, описывающих
множества значений. Это:
• порядковый тип — задающий множество значений внутри указанного
интервала;
• перечислимыпй тип — задающий множество значений, перечисленных
внутри фигурных скобок и через запятую.
М н о ж е с т в о я з ы к а Object Pascal — это набор з н а ч е н и й порядкового
и л и перечислимого типа. М н о ж е с т в о определяется к л ю ч е в ы м словом
set of.
Создание порядкового и перечислимого типов имеет следующее
формальное описание:
Идентификатор
Идентификатор
Идентификатор
Идентификатор
=
=
=
=
Начальное_значение .. Конечное_значение;
{Значение^
};
Значение^.. Значением ;
set of пор дковый или перечислимый тип.
Например:
type
TMyColor = {Red,Blue,Yellow}; {Объявление перечислимого типа}
TMyClr = s e t of TMyColor; {Объявление типа множество}
85
Курс
Введение в программирование
var
ValC1, ValC2: TMyClr; {Объявление переменных созданных типов}
begin
ValC1 := [ B l u e ] ;
{Присвоение значения переменной типа
множество}
ValC2 := ValC1+[ Red];
end.
Начальным и к о н е ч н ы м значением интервала для порядкового типа
могут быть:
• символы из кодовой таблицы A S C I I (например, ц и ф р ы или буквы);
• любой диапазон значений ранее объявленного перечислимого типа.
Перед работой с переменной множественного типа ее следует п р о инициализировать. Значения и н и ц и а л и з а ц и и указываются в квадратных
скобках.
Например:
type TMylnts = 1..500;
TIntSet = s e t o f TMylnts;
var s e t 1 : TIntSet;
{Объявление переменной типа множество}
begin
set1:=[1,2,3,4];
{Инициализация переменной типа множество}
end.
•
•
•
•
•
Над множеством допустимы следующие операции:
объединение множеств ( + );
разность (-);
умножение (*);
сравнение (<=, >=, =, <>);
принадлежность множеству (in).
Например:
type
CountType = 1..9;
{Порядковый тип: значения от 1 до 9}
LowerCharType = а..я;
AType = (A1, A2, A3, A4, A5);
AType3 = A3..A5;
{Порядковый тип: значения A3, A4 и A5}
ATypeSet = s e t of AType3; {Множество на основе порядкового типа}
LetterType = s e t of 'A'..'Z; {Множество
LetterType }
var
aset: ATypeSet; { Объ вление переменной типа множество}
begin
86
Лекция 9
Структурированные типы данных языка Object Pascal
aset:= [A3] + [A4];
aset:= aset
end.
[A4];
{ Присвоение значени переменной
множественного типа}
{Вычитание множеств}
Каждая переменная множественного типа может иметь значение —
множество. Д л я изменения значений переменной множественного типа
могут использоваться операции объединения (+) и разности (-) множеств.
Например:
begin set1:=set1
+[5,6]; end.
Для определения принадлежности значения некоторому множеству
используется операция i n .
Например:
begin
i f 5 i n set1
then ShowMessage('Значение принадлежит множеству s e t 1 ' ) ;
end.
Массивы
В я з ы к е Object Pascal м о ж н о создавать одномерные и многомерные
массивы. Все элементы массива имеют одинаковый тип.
Одномерный массив я з ы к а Object Pascal имеет следующее формаль¬
н о е описание:
Идентификатор: array [нач_индекс..кон_индекс] of тип_массива;
Например:
type
R e a l A r r = array[1..100] of Real;
var
i n t 1 : a r r a y [ 1 . . 2 0 ] of Integer;
i n t 2 : a r r a y [ 1 . . 2 0 ] of Integer;
i n t 3 , i n t 4 : a r r a y [ 1 . . 1 0 ] of Integer;
r e a l 1 : a r r a y [ 1 . . 1 0 ] of Real;
begin
Int1 := Int2;
end.
87
Курс
Введение в программирование
Массивы могут объявляться как константы.
Например:
type
TCub = a r r a y [ 0 . . 1 , 0..1, 0..1] of Integer;
const
cub1: TCube = ( ( ( 0 , 1), (2, 3 ) ) , ((4, 5), ( 6 , 7 ) ) ) ;
{ Элементы массива cub1 будут содержать следующие значения:
cub1 [0,0,0] = 0
cub1 [0,0,1] = 1
cub1 [0,1,0] = 2 и т. д.
}
Массив символов объявляется как массив переменных типа Char.
Символьный массив может быть доступен через указатель на массив типа
PChar.
Строки м о ж н о реализовывать как символьные массивы, ограничен
н ы е 0-символом (#0).
Например:
const
TempString: a r r a y [ 0 . . 8 ] of Char = 'Строка'#0;
var
P: PChar;
{Указатель на строку}
begin
P := ' Строка';
P := @TempString; {Переменная P указывает на значение 'Строка'}
end.
Массив символов типа Char и значение типа PChar эквивалентны.
Например:
var
MyArray: a r r a y [ 0 . . 5 ] of Char;
MyPointer: PChar;
begin
MyArray := 'array';
MyPointer := MyArray;
MyProc(MyArray);
{ Эквивалентно вызову
end.
MyProc(MyPointer);}
М н о г о м е р н ы й массив имеет следующее формальное описание:
88
Лекция 9
Структурированные типы данных языка Object Pascal
аггау[диапазон_первого,индекса
диапазон^_индекса] o f базовый_тип;
a r r a y [ диапазон] o f a r r a y [ диапазон] o f a r r a y [ диапазон] of тип;
Так, объявление
type MyMassiv = a r r a y [ 1 . . 1 0 ] of a r r a y [ 1 . . 7 0 ] of Integer;
эквивалентно объявлению
type MyMassiv = array[1..10,
1..70] of Integer;
Например:
type MyAr = array[1..10,
begin
MyAr[1,49]:= 49;
end.
1..50] of Real;
П о п р и н ц и п у выделения памяти под массив массивы языка Object
Pascal делятся на статические и динамические.
Память под статический массив выделяется при его создании.
Динамический массив не имеет фиксированного размера или длины.
П р и объявлении динамического массива память под него не выделя
ется. Выделение памяти происходит каждый раз при присвоении значе
н и я массиву или при вызове процедуры SetLength.
Создание динамического массива имеет следующее формальное
описание:
a r r a y o f тип_элементов_массива;
Например:
var MyAr: a r r a y of Integer; {Объявление динамического массива}
{Определение количества элементов в динамическом массиве:}
SetLength(MyAr, 10);
Элементы динамического массива всегда индексируются с 0. П е р е
менная типа динамического массива является указателем, и к ней п р и м е
н и м ы операции над указателями. Для освобождения памяти, занимаемой
д и н а м и ч е с к и м массивом, м о ж н о присвоить значение n i l переменной,
ссылающейся на массив. Количество элементов динамического массива
89
Курс
Введение в программирование
определяется процедурой SetLength. Ф у н к ц и я Length возвращает количе¬
ство элементов в динамическом массиве.
П р и сравнении двух переменных типа динамического массива вы¬
полняется сравнение их ссылок, а не значений их элементов.
Например:
var
A, B: a r r a y of Integer;
begin
SetLength(A, 1); SetLength(B, 1);
A[0] := 2; B[0] := 2;
{A[0] = B[0] вернет значение True}
{A = B вернет значение False}
end.
Для усечения динамического массива можно использовать функцию Copy.
Например:
var
A: a r r a y of Integer;
begin
SetLength(A, 50);
A := Copy(A, 0, 10); {Оставляет 10 элементов массива A}
end.
Если при объявлении ф у н к ц и и или процедуры формальный пара
метр определяется к а к a r r a y o f тип_массива, то эта ф у н к ц и я или проце¬
дура может получить в качестве фактического параметра любой динами¬
ческий или статический массив указанного типа вне зависимости от его
размера и индексации его элементов.
Записи
Запись представляет собой структуру, состоящую из набора полей
различных типов. Каждый элемент записи называется полем. Каждое по¬
ле имеет свой идентификатор и свой тип.
Запись может иметь поля двух видов:
• фиксированные поля, которые всегда присутствуют в создаваемом э к
земпляре записи;
• вариантные поля (располагаются только после ф и к с и р о в а н н ы х п о
лей), для которых память при создании экземпляра записи выделя
ется только под одно самое наибольшее поле из варианта.
Объявление типа записи завершается ключевым словом end;.
90
Лекция 9
Структурированные типы данных языка Object Pascal
Например:
type
MyDateRec = record
Year: Integer;
Month: 1..12;
Day: 1..31;
end;
var
Record1, Record2: MyDateRec;
{Объявление переменных}
begin
{Доступ к полям записи: }
Record1.Month := 11;
Record1.Day := 22;
{ Доступ к пол м записи:}
with Record1 do
begin
Year := 2004; Month := 11; Day := 22;
end;
{Копирование значений полей записей одного типа }
Record2:= Record1;
Переменная типа записи может быть объявлена одновременно с оп¬
ределением полей записи.
Например:
var
S: record
Name: s t r i n g ;
Age: Integer;
end;
Запись, состоящая из одних вариантных полей, реализует тип, в н е
котором роде аналогичный типу union для я з ы к а С + + .
Вариантные поля позволяют на основе одного типа записи создавать
экземпляры записей, содержащие поля разных типов. Это позволяет зна
чительно экономить память.
Объявление записи имеет следующее формальное описание:
type имя_типа_записи = record
список_полей: тип;
{фиксированные поля}
91
Курс
Введение в программирование
case тег: тип_варианта o f
{вариантные поля}
константа_или_список: (вариант_1);
константа_или_список: (варианту);
end;
Описание каждого фиксированного поля состоит и з его и д е н т и ф и
катора (или списка идентификаторов) и типа. О п и с а н и я полей разделя
ются точкой с запятой. Вариантная часть объявления записи начинается
с зарезервированного слова case.
П р и определении вариантной части тег и символ двоеточия могут
быть опущены в том случае, если тип варианта описывает существующий
тип или каждая константа (константа_или_список) в вариантной части я в
ляется значением типа тип_варианта.
Тип варианта н е может быть д л и н н о й строкой, динамическим мас
сивом, типом V a r i a n t или интерфейсом, н о о н может быть указателем на
эти типы.
Например:
type
TPerson = record
FirstName, LastName: s t r i n g [ 4 0 ] ;
case b l : Boolean of
{Вариантные поля}
True: ( s t r 1 : s t r i n g [ 4 0 ] ) ;
F a l s e : ( s t r 2 : s t r i n g [ 2 0 ] ; date1: TDate);
end;
TShapeList = (Rectangle, C i r c l e , Other, E l l i p s e ) ;
TFigure = record
case TShapeList o f
Rectangle: (Height, Width: Real);
C i r c l e : (Radius: Real);
E l l i p s e , Other: ( ) ;
end;
П р и м е н я я вариантные поля, м о ж н о одинаково трактовать д а н н ы е
различных типов, используя для доступа к н и м вариантные поля соответ¬
ствующих типов.
Файлы
Файл представляет собой упорядоченный набор элементов одного
типа.
92
Лекция 9
Структурированные типы данных языка Object Pascal
Стандартные процедуры ввода и вывода используют предопределен¬
н ы й т и п T e x t F i l e , или Text, который реализует файл к а к упорядоченный
набор строк символов.
Объявление типа «файл» и создание переменных файлового типа
имеет следующее формальное описание:
type тип_файла = f i l e of тип;
var
идентификатор: f i l e
of тип_файла;
Тип, указываемый после ключевых слов f i l e of, может быть произ¬
водным типом или базовым типом. Так, в качестве типа м о ж н о указать
string[число_символов] или array[нач_инд.. кон_инд] of Char.
Объявление нетипизированного файла имеет следующее формаль¬
н о е описание:
var идентификатор:
file;
Для создания переменной файлового типа следует предварительно
объявить файловый т и п , а затем объявить переменную созданного типа,
или сразу объявить переменную, указав используемый т и п к а к файловый.
Например:
type
Phone = record Name: s t r i n g [ 3 0 ] ; PhoneNumber: s t r i n g [ 2 0 ] ;
end;
PhoneList = f i l e of Phone; {Объявление файлового типа}
var
book1: PhoneList;
{Объявление переменной файлового типа}
book2: f i l e of Phone; {Объявление переменной с указанием типа
как файлового типа}
93
Курс
Введение в программирование
Глава .4. Объектно-ориентированное
программирование
Лекция 10. С++. Классы. Механизмы наследования.
Объектные типы
Терминология объектно-ориентированного
программирования
Объектно-ориентированное программирование позволяет опериро
вать в терминах классов: определять классы, конструировать производ
н ы е классы, создавать объекты, принадлежащие классу, — экземпляры
класса.
Сначала в некоторых я з ы к а х п р о г р а м м и р о в а н и я п о я в и л с я т и п
s t r u c t , расширением которого стал тип c l a s s .
Класс определяет д а н н ы е (переменные) и поведение (методы). Д а н
н ы е и методы класса также называют членами класса. Класс рассматрива
ется к а к определяемый пользователем тип данных.
Объектом называется экземпляр некоторого класса. Объект создает
ся к а к переменная типа класса, которая используется для доступа к д а н
н ы м — членам класса и для вызова методов — членов класса.
Наследованием называется механизм, позволяющий производному
классу наследовать структуру данных и поведение другого класса, а также
наследовать поведение, объявленное в интерфейсах и абстрактных классах.
Наследование позволяет определять новые классы в терминах суще¬
ствующих классов.
В объектно-ориентированном программировании наследование мо¬
жет быть:
• множественным, п о з в о л я ю щ и м производному классу наследоваться
одновременно от нескольких классов (например, так реализован м е
ханизм наследования в С + + ) ;
• простым, когда производный класс имеет только один наследуемый
класс (например, так реализованы я з ы к и Java и Object Pascal).
Наследуемый класс принято называть базовым классом, или роди¬
тельским классом (классом-предком, суперклассом).
Производный класс, наследующий структуру данных и поведение
своего базового класса, иногда также называется дочерним классом
(классом-потомком, подклассом).
94
Лекция 10
С++. Классы. Механизмы наследования. Объектные типы
В производном классе м о ж н о переопределять методы базового клас
са и добавлять новые методы. Непосредственным базовым классом н а з ы
вается класс, от которого порожден производный класс следующего уров
ня иерархии:
А
Базовый класс класса С и
непосредственный базовый класс класса B
B
Непосредственный базовый класс класса C
1
C
Производный класс
Полиморфизмом называется способность различных объектов п о разному обрабатывать одинаковые сообщения.
Инкапсуляция
позволяет работать в терминах объектов и скрывать
и х п е р е м е н н ы е и м е т о д ы . И с п о л ь з о в а н и е и н к а п с у л я ц и и дает в о з м о ж
н о с т ь м о д и ф и ц и р о в а т ь в н у т р е н н ю ю р е а л и з а ц и ю о б ъ е к т а без в л и я н и я
н а п р о г р а м м у в ц е л о м д о тех п о р , п о к а н е и з м е н я е т с я и н т е р ф е й с с
объектом.
В языках программирования инкапсуляция поддерживается реали
зацией модификаторов доступа, таких к а к protected — для з а щ и щ е н н ы х
членов класса на уровне класса, и private — для полностью з а щ и щ е н н ы х
членов класса.
Объектно- ориентированное программирование
на я з ы к е С + +
В настоящее время понятие я з ы к а программирования неотрывно
связано со средой программирования, в которой разрабатываются п р и л о
ж е н и я . Для я з ы к а С + + наиболее развитыми и популярными средами
программирования являются:
• Visual Studio.NET;
• Borland Developer Studio ( С + + Builder).
Среда программирования Visual Studio.NET предназначена для с о
здания приложений не только на я з ы к е С + + , но и на таких популярных
языках, как C# и V i s ^ l Basic. Иногда для с о к р а щ е н и я говорят, что проек
тирование приложений на C++ в Visual Studio.NET реализуется средой
Visual C++.
Visual C++ позволяет разрабатывать приложения как в терминах
традиционного модульного программирования, так и с п р и м е н е н и е м
объектно - ориентированного программирования.
95
Курс
Введение в программирование
Структура приложения на языке С++
П р и л о ж е н и е состоит из модулей трансляции — файлов исходного к о
да на я з ы к е С + + . Каждый модуль трансляции представляется файлом ре
ализации класса и заголовочным файлом (компилятор позволяет з а п и с ы
вать всю и н ф о р м а ц и ю — объявление и реализацию — в один файл, но это
оправданно только для маленьких программ).
Проектом в терминологии Visual C++ называется совокупность всех
модулей трансляции, файлов ресурсов и описания конфигурации.
Разработка любого приложения в Visual C++ начинается с создания
проекта. Visual Studio.NET предоставляет ш а б л о н ы для создания различ
ных видов приложений (консольные приложения, M F C - п р и л о ж е н и я ,
DLL-библиотеки, приложения управляемого кода и т.п.).
Консольное приложение
— это п р и л о ж е н и е , н е и с п о л ь з у ю щ е е
Windows-окна для обработки сообщений от пользователя. Точкой входа в
консольное приложение в я з ы к е С + + является метод main.
После того как создан шаблон приложения заданного вида, и н ф о р
м а ц и я обо всех файлах проекта отображается в о к н е проектов среды
Visual C++.
Заголовочный файл содержит объявления используемых данных.
Я з ы к C++ поддерживает соглашение о раздельной к о м п и л я ц и и : каждый
С + + - м о д у л ь м о ж н о компилировать отдельно. Для того чтобы несколько
модулей могли использовать одни и те ж е данные, объявление этих д а н
ных выносят в заголовочный файл. П р и н я т о , что и м я заголовочного ф а й
ла имеет р а с ш и р е н и е h.
Все подключаемые к модулю заголовочные ф а й л ы указываются в
начале модуля директивой препроцессора #include.
Например:
#include " s t d a f x . h "
#include <iostream>
И м я подключаемого файла в директиве препроцессора #include мо¬
жет быть указано:
• в двойных кавычках — в этом случае препроцессор сначала выполня¬
ет п о и с к данного файла в том ж е каталоге, в котором расположен
файл, содержащий директиву препроцессора #include, а затем в ка
талогах, определяемых опцией к о м п и л я ц и и и переменной среды
INCLUDE.
• в угловых скобках — при этом исключается п о и с к и м е н и файла в том
же каталоге, в котором расположен файл, содержащий директиву
препроцессора #include.
96
Лекция 10
С++. Классы. Механизмы наследования. Объектные типы
Файл, содержащий реализацию методов, объявленных в заголовоч
н о м файле, иногда называется исходным файлом.
Каждая программа должна иметь точку входа и может содержать
описание одного или нескольких классов.
Точкой входа в программу в приложении, формируемом по шаблону
в среде Visual C++, является метод _tmain, заменяемый при к о м п и л я ц и и
на метод main.
М и н и м а л ь н о й программой н а С + + является следующий код:
i n t main() {}
Эта программа определяет ф у н к ц и ю с именем main, которая н е и с
пользует параметров и н е выполняет никаких действий.
Тело метода в языке С + + указывается в фигурных скобках. Перед име
нем метода указывается тип возвращаемого значения. Если метод н е воз
вращает никакого значения, то его тип обозначается ключевым словом void.
Объявление и реализация класса в языке С++
Создаваемый класс должен быть объявлен и реализован.
Объявление класса в я з ы к е С + + может иметь следующее формаль¬
н о е описание:
class имя_класса : список_базовых_классов {
public:
// Модификатор доступа относится ко всем перечисленным
// после него членам до следующего модификатора доступа
// Объявление общедоступных членов класса
protected: // Объявление членов класса, доступных только
//для производных классов
private:
// Объявление защищенных членов класса
}
С п и с о к базовых классов указывается после и м е н и класса через с и м
вол двоеточия (:), разделяется запятыми и может иметь модификаторы
доступа.
Например:
c l a s s MyClass :
p u b l i c ClassA,
p u b l i c ClassB, p r i v a t e ClassC {}
В я з ы к е С + + считается, что если модификатор доступа для класса
или члена класса н е указан, то п о умолчанию предполагается м о д и ф и к а
тор доступа private ( з а щ и щ е н н ы й доступ). Для членов структур, объявля97
Курс
Введение в программирование
емых ключевым словом struct, по умолчанию модификатор доступа пред¬
полагается равным p u b l i c .
М о д и ф и к а т о р доступа базового класса позволяет определить, какие
переменные и методы базового класса будут доступны из производного
класса. М о д и ф и к а т о р доступа, указываемый перед именем базового клас
са, определяет следующие правила доступа к переменным и методам ба¬
зового класса из производного класса:
• p u b l i c — в производном классе доступны все переменные и методы
базового класса с модификаторами доступа p u b l i c и p r o t e c t e d , и эти
члены класса имеют те ж е права доступа;
• p r o t e c t e d — члены базового класса с модификаторами доступа p u b l i c
и p r o t e c t e d доступны к а к p r o t e c t e d , а с модификатором доступа
p r i v a t e — недоступны.
• p r i v a t e — ч л е н ы базового класса с модификаторами доступа p u b l i c и
p r o t e c t e d доступны как p r i v a t e , а с модификатором доступа p r i ¬
vate — недоступны.
Например:
c l a s s BaseClass
{ public:
i n t PublicFunc();
protected:
i n t ProtectedFunc();
pr i v a t e :
i n t Pr i v a t e F u n c ( ) ;
};
c l a s s D e r i v e d C l a s s l : p u b l i c BaseClass {
// Наследуемая функция PublicFunc доступна как p u b l i c
// Наследуемая функция ProtectedFunc доступна как p r o t e c t e d
};
c l a s s D e r i v e d C l a s s 2 : p r i v a t e BaseClass {
// Наследуема функци PublicFunc доступна как p r i v a t e
// Наследуема функци ProtectedFunc доступна как p r i v a t e
};
i n t main() { }
В теле объявления класса указываются модификаторы доступа, о п и
сывающие права доступа для переменных и методов класса:
• модификатор доступа относится ко всем перечисленным после него
членам до следующего модификатора доступа;
• о д и н и тот ж е м о д и ф и к а т о р д о с т у п а м о ж е т у к а з ы в а т ь с я несколь¬
ко р а з ;
98
Лекция 10
С++. Классы. Механизмы наследования. Объектные типы
• после модификатора доступа ставится символ «двоеточие»;
• если модификатор доступа не указан, то по умолчанию предполага¬
ется p r i v a t e .
Для доступа к членам класса используется операция принадлежнос
ти : : , указываемая после идентификатора класса. Для доступа к членам
экземпляра класса используются операции . и ->.
Для доступа к объекту самого класса внутри метода члена класса и с
пользуется ключевое слово t h i s .
Например:
class A {
public:
int i ;
A:: Func1() { return t h i s - > i ;
Func1();}
}
// t h i s - указатель класса A
Конструкторы класса
Конструктором называется метод, вызываемый при создании объек¬
та данного класса. Класс может иметь несколько конструкторов, отлича¬
ющихся списком параметров.
Деструктором называется метод, вызываемый при разрушении объ¬
екта данного класса. И м е н а конструктора и деструктора совпадают с име¬
н е м класса, но перед именем деструктора указывается символ ~.
П р и создании объектов последовательно вызываются конструкторы
всех его базовых классов. Вызов деструкторов при уничтожении объекта
происходит в обратном порядке.
Если конструктор базового класса имеет с п и с о к параметров, то для
его использования в производном классе следует создать конструктор
производного класса с таким ж е списком параметров.
П р и создании нового класса среда Visual C++ автоматически созда¬
ет заголовочный файл и файл реализации класса с конструктором и дест¬
руктором без параметров.
Создание объекта
Для создания объекта (экземпляра данного класса) следует объявить
переменную типа «указатель на класс», а затем создать объект, выполнив
оператор new с указанием используемого конструктора.
Например:
A* ca;
ca= new A ( ) ;
Эти ж е действия м о ж н о записать одним оператором.
99
Курс
Введение в программирование
Например:
A* ca= new A ( ) ;
Для того чтобы м о ж н о было использовать конструктор с параметра
ми, значения параметров необходимо указать при создании объекта.
Вложенные классы
Я з ы к С + + допускает использование вложенных классов — внутри
тела одного класса содержится объявление других классов.
Например:
class A
{
public:
A(void);
~A(void);
class B {
// Вложенный класс
B ( v o i d ) {};
~ B ( v o i d ) {};
char s S t r 2 [ 3 ] ;
};
};
Объектные типы
Тип данных всегда определяет размер памяти, которая будет выделе¬
на под переменную данного типа при ее создании.
П р и объявлении переменной объектного типа (типа класса) созда
ются переменные члены класса и вызывается конструктор класса. П р о и з
водные т и п ы на основе классов позволяют получать доступ к членам
класса.
Переменная, объявленная к а к указатель на класс, применяется для
доступа к методам и переменным членам класса. В следующей таблице
приведен синтаксис, используемый при работе с указателями на ч л е н ы
класса.
Например:
#include <iostream.h>
class A
// Объ вление класса A
100
Лекция 10
С++. Классы. Механизмы наследования. Объектные типы
{ public:
int j1;
A(void);
~A(void);};
v o i d main() {
i n t A::*pToj = &A::j1; //
//
//
A jA;
A *pjA = & jA;
//
//
int j ;
jA.*pToj = 123;
//
//
j = pjA ->*pToj;
//
s t d : : c o u t << j << "\n";
Объявление производного типа pToj
как указателя на член класса j 1
Объявление переменной объектного типа A
Объявление указателя на эту переменную
( объект)
Присваивание значения переменной
jA:
используя *
Получение значения, используя ->*
}
Преобразование объектных типов
Указатель на класс может быть преобразован к указателю на базовый
класс в двух случаях:
• если базовый класс является д о с т у п н ы м и преобразование одно¬
значно;
• если указано я в н о е преобразование типа указателя.
Например:
class A
{public:
i n t a1;
i n t Fa();
};
class B : public A
{public:
i n t b1;
i n t Fb();
};
B bObject;
A *pA = &bObj;
B *pB = &bObj;
// А — базовый класс
// В — производный класс
//
//
//
//
//
//
//
Объект типа B
Преобразование типа ограничивает
доступ к членам класса B и разрешает
доступ только к членам базового класса
Нет преобразования типа и следовательно
разрешен доступ как к членам класса B,
так и к членам класса А.
101
Курс
Введение в программирование
pA-> Fa ( ) ;
pB-> Fa ( ) ;
// Правильно: вызов функции члена класса A.
// Правильно: вызов функции, наследуемой от
// класса A
// Вызов pA-> Fb ( ) ;
ошибочен: функци Fb недоступна
// через указатель на базовый класс А
Указатели на ч л е н ы класса или структуры не могут рассматриваться
как обычные указатели и для них не выполняется стандартное преобразо¬
вание типа.
Квалификация имен
К в а л и ф и к а ц и я и м е н используется для однозначного п о н и м а н и я
указываемого и м е н и .
Для к в а л и ф и к а ц и и и м е н и могут использоваться следующие опера¬
торы: :: (оператор принадлежности); . (оператор доступа к члену класса
посредством имени); -> (оператор доступа к члену класса через указа¬
тель).
102
Лекция 11
С++. Методы - члены класса. Дружественные классы и члены класса
Лекция 1 1 . С++. Методы - члены класса.
Дружественные классы и члены класса
Методы - члены класса
В терминологии объектно-ориентированного п р о г р а м м и р о в а н и я
ф у н к ц и и также называются методами или методами — членами класса,
для того чтобы подчеркнуть, что конкретная ф у н к ц и я является членом
некоторого класса.
П о стандарту A N S I C , используемому компилятором Visual C + + ,
любая используемая в модуле к о м п и л я ц и и ф у н к ц и я должна иметь прото
тип, включающий в себя т и п ф у н к ц и и , и м я ф у н к ц и и и с п и с о к парамет¬
р о в с их типами. Прототип — это некоторое предварительное описание
ф у н к ц и и , заканчивающееся символом ;.
Прототип функции должен быть вставлен во все модули компиляции,
использующие функцию. Д л я небольших программ прототип функции
обычно записывается в модуль компиляции. Д л я программ, создаваемых
средствами Visual C++, и программ, состоящих из нескольких модулей,
прототип функции указывается в заголовочном файле. Объявление функ
ции должно однозначно соответствовать ее прототипу и может находиться
в любом модуле компиляции (для которого доступен прототип функции).
Прототип метода, являющегося членом некоторого класса, записывает
ся в заголовочном файле, содержащем объявление класса в теле этого класса.
Метод — член класса может иметь следующие модификаторы доступа:
• public — общедоступный метод;
• protected — метод, доступный только для членов и объектов данного
класса и наследуемых классов (наследуемых с модификаторами до¬
ступа p u b l i c или protected);
• private — з а щ и щ е н н ы й метод, доступный только внутри класса.
Прототип метода может иметь следующее формальное описание:
модификатор_доступа тип_метода имя_метода(список_параметров);
Объявление метода может иметь следующее формальное описание:
модификатор_доступа тип_метода имя_метода(список_параметров)
{ тело_метода }
Тип метода является типом возвращаемого методом значения и м о
жет быть л ю б ы м допустимым базовым или производным типом, включая
и т и п указателя.
103
Курс
Введение в программирование
Указатели типа void могут использоваться для объявления парамет
ров метода в том случае, если тип этих параметров на момент к о м п и л я ц и и
неизвестен.
Например:
v o i d Fx(void *pV);
//Прототип метода
piVar=new i n t ;
pfVar=new f l o a t ;
Fx(piVar);
// Вызов метода дл
параметра типа i n t
Fx(pfVar);
// Вызов метода дл
параметра типа f l o a t
// Реализация метода
v o i d Fx(void *pV) {*pV=12345;}
М е т о д , в о з в р а щ а ю щ и й указатель, з а п и с ы в а е т с я с л е д у ю щ и м о б
разом:
тип *имя_метода(список_параметров).
С п и с о к ф о р м а л ь н ы х параметров — это значения, передаваемые в
ф у н к ц и ю . К а ж д ы й элемент этого списка может иметь л ю б о й допусти¬
м ы й тип.
Я з ы к С + + д о п у с к а е т передачу п а р а м е т р о в по з н а ч е н и ю и п о
с с ы л к е и л и у к а з а т е л ю . П а р а м е т р ы , п е р е д а в а е м ы е по з н а ч е н и ю , п р и
в ы п о л н е н и и п р о г р а м м ы з а н о с я т с я в стек, и д л я б о л ь ш и х р а з м е р о в
структур и л и м а с с и в о в м о ж е т в о з н и к н у т ь с и т у а ц и я п е р е п о л н е н и я сте¬
ка. П а р а м е т р ы , п е р е д а в а е м ы е к а к с с ы л к и и л и у к а з а т е л и , н е копиру¬
ю т с я в стек.
И з м е н е н и е значений самих параметров происходит только для пара¬
метров, переданных по ссылке или указателю. П р и передаче параметра по
значению метод изменяет не сам параметр, а его к о п и ю .
С п и с о к параметров может включать параметры, и м е ю щ и е значения
по умолчанию. Такие параметры указываются в к о н ц е списка параметров.
Значение по умолчанию будет использовано только в том случае, если
число переданных параметров м е н ь ш е числа указанных формальных па¬
раметров в о п и с а н и и метода.
Я з ы к C++ разрешает рекурсивный вызов методов.
В методах класса м о ж н о использовать ключевое слово t h i s , я в л я ю
щееся указателем на объект данного класса. Это ключевое слово нельзя
использовать вне метода члена класса.
104
Лекция 11
С++. Методы - члены класса. Дружественные классы и члены класса
Создание метода - члена класса
Д л я того чтобы в среде Visual Studio . N E T добавить в класс н о в ы й м е
тод — член класса, следует в о к н е просмотра классов Class View выделить
с е к ц и ю с и м е н е м класса и в ы п о л н и т ь команду контекстного м е н ю
Add | Add Function, а затем в диалоге — мастере построения метода ввести
и м я метода, его т и п , а также определить с п и с о к параметров.
П р и добавлении метода — члена класса в ф а й л реализации класса
автоматически добавляется код реализации нового метода, а в заголовоч
н ы й ф а й л — объявление этого метода.
Методы с переменным числом параметров
Метод может иметь переменное число параметров: это указывается в
к о н ц е списка параметров символом многоточия ... . Методы с перемен¬
н ы м числом параметров д о л ж н ы иметь к а к м и н и м у м один о п и с а н н ы й
ф о р м а л ь н ы й параметр.
Д л я п р и м е н е н и я п е р е м е н н о г о ч и с л а п а р а м е т р о в м о ж н о использо¬
вать:
• макрос va_start(указатель_списка_параметров,последний_параметр) —
при и н и ц и а л и з а ц и и указателя и установке его на начало переменно¬
го списка параметров;
• макрос va_arg(указатель_списка_параметров, i ) — при выборе параме
тра и продвижении указателя в соответствии с его типом на следую¬
щ и й параметр;
• макрос va_end(укaзaтель_спискa_пaрaметров) — при установке указа
теля на с п и с о к параметров, р а в н ы й null, после извлечения значений
всех параметров;
• тип v a _ l i s t — для создания указателя на список параметров.
Например:
#include
#include
#include
i n t Fx (
<stdio.h>
// Библиотека, содержащая тип v a _ l i s t
<varargs.h>
<iostream>
i n t i 1 , ... ); // Прототип Функции
// с переменным числом параметров
void main( v o i d )
{// Вызов функции Fx с различным числом параметров
s t d : :cout<< Fx ( 100, 200) );
std::cout<< Fx ( 5 ) );
std::cout<< Fx ( -1,-3,45 ) );
}
105
Курс
Введение в программирование
i n t Fx ( i n t i 1 , ... )
{
// Реализаци функции
// с переменным числом параметров
i n t sumx, i ;
sumx = 0, i = i 1 ;
va_list list1;
// Список параметров
v a _ s t a r t ( l i s t 1 , i 1 );
// Инициализация списка параметров
w h i l e ( i != -1 )
{
sumx += i ;
i = v a _ a r g ( l i s t 1 , i n t ) ; //Извлечение следующего параметра
}
va_end(list1);
return( sumx );
}
Указатели на методы - члены класса и на функции
Указатели на методы и на ф у н к ц и и могут быть и с п о л ь з о в а н ы для пе¬
редачи метода в качестве параметра другому методу.
Объявление указателя на метод может иметь следующее ф о р м а л ь н о е
описание:
тип_метода (имя_класса::*имя_метода_указателя)(список параметров);
тип_функции (*имя_ функции_указателя)(список параметров);
И н и ц и а л и з а ц и я указателя может иметь следующее ф о р м а л ь н о е опи¬
сание:
тип_метода имя_класса::*имя_метода_указателя (список параметров)
=&имя_класса::имя_любого_метода;
тип_функции (*имя_ функции_указателя)(список параметров) =
&имя_функции;
Вызов метода, объявленного к а к указатель на метод, может быть вы¬
п о л н е н следующим образом:
(имя_объекта->*имя_ метода_указателя)( список параметров);
(*имя_ функции_указателя)( список параметров);
Д л я ф у н к ц и й , н о н е для методов — ч л е н о в класса, р а з р е ш е н а другая
ф о р м а вызова метода:
имя_ функции_указателя(список параметров);
(имя_ функции_указателя)(список параметров);
106
Лекция 11
С++. Методы - члены класса. Дружественные классы и члены класса
Объявление ф у н к ц и и , и м е ю щ е й в качестве параметра указатель на
метод, может иметь следующее ф о р м а л ь н о е о п и с а н и е :
тип_метода имя_метода (тип_метода_указателя
( список параметров));
(*имя_метода_указателя)
Вызов метода, использующего в качестве параметра указатель на ме¬
тод, может иметь следующее ф о р м а л ь н о е о п и с а н и е :
имя_метода(имя_объекта->*имя_метода_указателя);
имя_функции(имя_функции_указателя);
Разрешается создавать массив указателей на ф у н к ц и и .
П р и и с п о л ь з о в а н и и указателей на ф у н к ц и ю м о ж н о н е употреблять
о п е р а ц и ю р а з ы м е н о в а н и я или о п е р а ц и ю получения адреса.
Например:
c l a s s a1
{
public:
a1(void);
~a1(void);
i n t Fx1( i n t i 1 ) ;
i n t Fx2( i n t i 2 ) ;
};
a1: :a1(void){}
a1: :~a1(void){}
i n t a1::Fx1(int
return 1;}
i n t a1::Fx2( i n t i 2 ) { return 2;}
int ( *Fy_pointer )();
// Объ вление указател
i n t Fy ( ) ;
i n t _ m a i n ( i n t argc, char* a r g v [ ] )
на функцию
{
a1* a1Object = new a 1 ( ) ;
i n t (a1::*Fx_pointer)(int)=&a1::Fx2;
// Объявление и
// инициализация указателя на метод - член класса
int i ;
i=(a1Object->*Fx_pointer)(1);
// Вызов по указателю на метод
std::cout<<i;
i n t (*Fy_pointer)()=&Fy;
// инициализаци
107
// Объявление и
указател на функцию
Курс
Введение в программирование
std::cout<<( F y _ p o i n t e r ) ( ) ;
std::cout<<( * F y _ p o i n t e r ) ( ) ;
return 0;
}
i n t Fy ( )
// Вызов по указателю на
// функцию ( две формы)
{ r e t u r n 5;}
Встроенные функции
Встроенные ф у н к ц и и указываются оператором i n l i n e . П р и м е н е
н и е встроенных ф у н к ц и й может н е с к о л ь к о сократить время в ы п о л н е
н и я п р о г р а м м ы , т а к к а к к о м п и л я т о р встраивает к о д т а к о й ф у н к ц и и в
том месте п р о г р а м м ы , где указан ее вызов.
Например:
i n l i n e v o i d F x ( v o i d ) { std::cout«"Функция
Fx(void);
Fx"<<std::endl;}
// Этот код будет заменен компилятором
// на код встроенной функции
Перегрузка функций и методов
Я з ы к C + + позволяет выполнять перегрузку ф у н к ц и й и мето
д о в — ч л е н о в к л а с с а , т о есть в ы з ы в а т ь ф у н к ц и ю ( м е т о д ) с т е м ж е
именем, но с различными типами фактических параметров. Для со
з д а н и я п е р е г р у ж а е м о й ф у н к ц и и следует у к а з а т ь о т д е л ь н ы й п р о т о
тип и сделать отдельное объявление для каждого списка парамет
ров. Если ф у н к ц и и различаются только типом и имеют совпадаю
щ и е списки параметров, то для таких ф у н к ц и й перегрузка не допу
скается.
Для определения вызываемой перегружаемой функции учитыва
ются только списки параметров, а тип возвращаемого значения не
учитывается. П р и этом для соответствия списка параметров вызывае
м о й ф у н к ц и и м о ж е т п р и м е н я т ь с я п р е о б р а з о в а н и е т и п о в и соответст
в и е п о м н о г о т о ч и ю ( с о о т в е т с т в и е п о м н о г о т о ч и ю ? ) д л я ф у н к ц и й с пе¬
ременным числом параметров.
Дружественные члены класса
Дружественные члены класса (методы) позволяют получить доступ к
з а щ и щ е н н ы м модификатором p r i v a t e членам класса из методов других
классов. Методы и классы, объявляемые дружественными, иногда также
называются друзьями класса.
108
Лекция 11
С++. Методы - члены класса. Дружественные классы и члены класса
Если метод класса A внутри тела класса B объявляется с м о д и ф и к а
тором friend, что указывает на то, что он является другом класса, то из не¬
го р а з р е ш е н доступ ко всем членам класса B.
Например:
class A {
public:
i n t Fx();
class B { public:
}
friend i n t A::Fx();
pr i v a t e :
}
Дружественные классы
Объявление дружественного класса позволяет всем его методам по¬
лучить доступ ко всем переменным и методам другого класса.
Например:
class A {
public:
i n t Fx();
}
class B {
public:
friend class A;
pr i v a t e :
}
Дружественный класс или член класса будет доступен только в том
случае, если он был объявлен в области видимости самого класса или ра
нее во в н е ш н е й области видимости, внутри которой располагается об
ласть видимости, содержащая объявление класса с объявлениями друзей
класса.
Например:
class A {public:
// Класс расположен во внешней области видимости
i n t Fx1();
}
namespace c l a s s B {
class B {public:
f r iend c l a s s A;
f r i e n d c l a s s C;
pr i v a t e :
109
Курс
Введение в программирование
}
class C { public:
// Класс расположен в том же
// пространстве имен
i n t Fx2();
}
}
Д р у ж е с т в е н н ы е классы н е наследуются, и их дружественность н е я в
ляется т р а н з и т и в н о й .
Например:
class A {
class B {
class C {
i n t Fx();
}
f r i e n d c l a s s A;
f r i e n d c l a s s B;
class D : public B {
}
}
}
110
//
//
//
//
Класс А не является
дружественным классу С
Класс А не вл етс
дружественным классу D
Лекция 12
С++. Статические члены класса. виртуальные функции
Лекция 12. С++. Статические члены класса.
Виртуальные функции
Статические члены класса
П е р е м е н н ы е и ч л е н ы класса, объявленные с модификатором досту
па s t a t i c , называются статическими членами класса. Отатические пере
м е н н ы е и методы доступны без создания объекта данного класса. И м я
статической переменной квалифицируется именем класса с использова
н и е м операции принадлежности : :, а не именем экземпляра класса.
Например:
c l a s s A { p u b l i c : s t a t i c i n t i S t a t ; };
i n t m a i n ( i n t argc, char* a r g v [ ] ) {A:: i S t a t = 123;}
Статические методы могут вызывать и использовать только другие
статические методы и статические переменные. И з статического метода
нельзя выполнять вызов не статического метода — члена класса.
Статическую переменную м о ж н о рассматривать как аналог глобаль¬
н о й переменной, которая связана с конкретным классом.
Часто статические переменные называют п е р е м е н н ы м и класса, а не
статические переменные — переменными экземпляра.
Для статических переменных могут использоваться указатели.
Например:
class A
{ public:
s t a t i c i n t iStatVar;
};
i n t main( i n t argc, char* a r g v [ ] ) {
i n t A:: i S t a t V a r = 0;
i n t * p i S t a t V a r = &A:: i S t a t V a r ;
}
П р и использовании статических переменных указатели всегда я в л я
ются указателями на существующий тип (в д а н н о м примере — на тип int),
а не на тип класса.
Для того чтобы создать и использовать статическую переменную,
следует:
1.
Объявить (как правило, в заголовочном файле) статическую пере¬
менную как член класса.
111
Курс
Введение в программирование
Например: s t a t i c int i S t a t ; .
Д л я выделения памяти под эту переменную ее повторно следует
объявить в модуле к о м п и л я ц и и , в котором она будет использовать
ся, квалифицируя и м я статической переменной именем класса.
Например: i n t A:: i S t a t ;
3.
Выполнить и н и ц и а л и з а ц и ю статической переменной (по умолча
н и ю статическая переменная типа int имеет значение 0).
Например: A:: iStat=123;
И н и ц и а л и з а ц и ю статической переменной м о ж н о выполнять в теле
конструктора в том случае, если п р и создании объекта с использованием
этого конструктора память под статическую переменную уже выделена.
Однако инициализировать статическую переменную через конструктор в
форме
2.
имя_класса::имя_конструктора
: имя_стат_переменной(значение) { }
нельзя н и в к а к о м случае.
Для того чтобы создать статический метод — член класса в среде
Visual C + + , достаточно выделить в о к н е Class View секцию с именем
класса, в который будет вставлен создаваемый метод, и выполнить ко¬
манду контекстного меню Add | Add Function. А затем определить тип и и м я
создаваемого метода, список параметров, и отметить флажок S t a t i c , ука¬
з ы в а ю щ и й на то, что создаваемая ф у н к ц и я будет статической.
В результате выполненных действий среда Visual C++ добавит в за¬
головочный файл класса прототип создаваемой статической ф у н к ц и и , а в
файл реализации — код реализации создаваемой статической функции.
Например:
class A
{public:
a1(void);
~a1(void);
i n t Fx1( i n t i 1 ) ;
i n t Fx2( i n t i 2 ) ;
protected:
s t a t i c i n t Fstat1(void);
// Статическая функция доступна
//только для статических методов - членов
//данного класса и наследуемых классов
public:
s t a t i c i n t Fstat2(void);
// Общедоступная статическая
// функция
};
112
Лекция 12
С++. Статические члены класса. виртуальные функции
i n t m a i n ( i n t argc, char*
std::cout<<a1::Fstat2();
argv[]){
// Вызов статической функции
}
Реализация статической ф у н к ц и и записывается так ж е , как и реали
зация любого другого метода — члена класса. П р и этом ключевое слово
s t a t i c не указывается.
Например:
i n t A::FStat1(void)
{ r e t u r n 0; }
Виртуальные методы
Виртуальные методы объявляются в базовом классе с ключевым сло
вом v i rtual, а в производном классе могут быть переопределены. Прото¬
т и п ы виртуальных методов к а к в базовом, т а к и в производном классе
д о л ж н ы быть одинаковы.
Применение виртуальных методов позволяет реализовывать меха
низм позднего связывания, при котором определение вызываемого метода
происходит на этапе выполнения, а не на этапе компиляции. При этом вы
зываемый виртуальный метод зависит от типа объекта, для которого он вы
зывается. При раннем связывании, используемом для невиртуальных мето
дов, определение вызываемого метода происходит на этапе компиляции.
На этапе к о м п и л я ц и и строится таблица виртуальных методов, а к о н
кретный адрес проставляется уже н а этапе выполнения.
П р и вызове метода с использованием указателя н а класс действуют
следующие правила:
• для виртуального метода вызывается метод, соответствующий типу
объекта, н а который указывает указатель.
• для невиртуального метода вызывается метод, соответствующий т и
пу самого указателя.
В следующем примере иллюстрируется вызов виртуальных методов:
class A
// Объявление базового класса
{ public:
v i r t u a l void VirtMetod1();
// Виртуальный метод
v o i d Metod2();
// Невиртуальный метод
};
v o i d A::VirtMetod() { cout << "Вызван A::VirtMetod1\n";
}
v o i d A::Metod2() { cout << "Вызван A::Metod2\n"; }
class B : public A
// Объ вление производного класса
{public:
113
Курс
Введение в программирование
void VirtMetod1();
v o i d Metod2();
// Виртуальный метод
// Невиртуальный метод
};
v o i d B::VirtMetod1() {
cout << "B::VirtMetod1\n";}
v o i d B::Metod2() { cout << "B::Metod2\n"; }
v o i d main()
B aB;
// Объект класса B
B *pB = &aB;
// Указатель на
A *pA
= &aB;
// Указатель на
pA->VirtMetod1();
// Вызов метода
pB->VirtMetod1();
// Вызов метода
pA->Metod2();
// Вызов метода
pB->Metod2();
// Вызов метода
объект класса B
объект класса A
V i r t M e t o d класса B
V i r t M e t o d класса B
Metod2 класса A
Metod2 класса B
Результатом в ы п о л н е н и я этой программы будут следующие строки:
Вызван B::VirtMetod1
Вызван B::VirtMetod1
Вызван A::Metod2
Вызван B::Metod2
Чисто виртуальной ф у н к ц и е й называется виртуальная ф у н к ц и я ,
указанная с инициализатором =0.
Например:
v i r t u a l v o i d F1( i n t ) =0;
Объявление класса может содержать виртуальный деструктор, и с
пользуемый для удаления объекта определенного типа. Однако виртуаль
ного конструктора в я з ы к е С + + не существует. Некоторой альтернативой,
позволяющей создавать объекты заданного типа, могут служить вирту
альные методы, в которых выполняется вызов конструктора для создания
объекта данного класса.
Например:
c l a s s A{
public:
A();
A (const A&);
v i r t u a l A* v i r t _ o b j e c t 1
v i r t u a l A* v i r t _ o b j e c t 2
( ) { r e t u r n new A ( ) ; }
( ) { r e t u r n new A ( * t h i s ) ; }
}
114
Лекция 12
С++. Статические члены класса. виртуальные функции
Виртуальные классы
Для того чтобы при множественном наследовании один и тот ж е ба
зовый класс не порождал для объекта производного класса несколько
объектов базового класса, при объявлении производного класса такой ба
зовый класс указывается с ключевым словом v i rtual и называется вирту¬
альным классом.
Например:
class A : v i r t u a l public B
{
}
Абстрактные классы
Абстрактным классом называется класс, который содержит хотя бы
одну чисто виртуальную ф у н к ц и ю .
Абстрактный класс не может быть я в н о использован для создания
объектов.
Как правило, абстрактный класс применяется для описания интерфей
са, который должен быть реализован всеми его производными классами.
Если класс, производный от абстрактного класса, не содержит реа
лизации всех его чисто виртуальных ф у н к ц и й , то о н также является абст¬
р а к т н ы м классом.
Шаблоны методов
Ш а б л о н ы методов позволяют описывать одинаковую реализацию
для различных типов параметров.
Ш а б л о н метода позволяет описать одну реализацию метода для всех
допустимых значений параметров. Фактически шаблон метода заменяет
набор перегружаемых методов с р а з л и ч н ы м и типами параметров.
Шаблон метода — это еще одно проявление полиморфизма языка С + + .
Ш а б л о н ы методов используют в качестве параметра тип переменной.
В момент к о м п и л я ц и и при вызове метода, не имеющего прототипа,
выполняется п о и с к шаблона метода, из которого вызываемый метод мо¬
жет быть сгенерирован.
Ш а б л о н метода указывается ключевым словом template, за которым
в угловых скобках указывается с п и с о к типов, используемых для параме
тров ф у н к ц и и и типа возвращаемого значения.
Например:
template <class T1>
T1 Fx (T1 x, T1 y) { r e t u r n x+y;}
115
Курс
Введение в программирование
П р и использовании шаблона компилятор заменит для вызываемого
метода тип шаблона на тип, указанный при вызове метода (T1 на i n t в
следующем примере).
Например:
i n t i1=1;
i n t i2=2;
std::cout<<Fx( i 1 , i 2 ) ;
Шаблоны классов
Ш а б л о н ы классов позволяют определить параметризированный тип.
Ш а б л о н ы классов аналогично шаблонам ф у н к ц и й позволяют на
этапе к о м п и л я ц и и создавать определения классов.
Ш а б л о н класса указывается ключевым словом template, за которым
в угловых скобках указывается список типов для создания параметризированного класса. И м я шаблона класса указывается после ключевого сло¬
ва c l a s s .
Для создания объекта на основе шаблона класса после и м е н и шабло
на в угловых скобках указывается конкретный тип:
имя_шаблона_класса <тип> имя_объекта.
Например:
template <class T1>
class A
// Описание шаблона класса
{
T1 x,y;
public:
A();
~A();
T1 F x ( ) ;
v o i d Fy(T1 a, T1 b);
};
template <class T1> A< T1>::A() {}
// Реализация методов
// шаблона класса
template <class T1> A< T1>::~A() {}
template <class T1>T1 A< T1>::Fx(){ return x*y;}
template <class T1>void A< T1>::Fy(T1 a, T1 b) {x=a; y=b;}
i n t main( i n t argc, char* a r g v [ ] )
{
i n t i1=1;
116
Лекция 12
С++. Статические члены класса. виртуальные функции
i n t i2=2;
double x=1.5;
double y=2.5;
A <int> F1;
// Создание объекта с использованием
// шаблона класса
A <int> *pF1=&F1;
// Указатель на объект
// параметризированного типа
pF1->Fy(i1,i2);
s t d : :cout<<pF1->Fx()<<std::endl;
A <double> F2;
A <double> *pF2=&F2;
pF2->Fy(x,y);
std::cout<<pF2->Fx()<<std::endl;
return 0;
}
Работа с п а м я т ь ю
Свободная память, которую м о ж н о заказывать в процессе выполне
н и я программы, называется динамической памятью. Для выделения н е
прерывного блока памяти м о ж н о использовать ф у н к ц и ю m a l l o c ( ) , а для
освобождения — ф у н к ц и ю f r e e ( ) . Прототипы этих ф у н к ц и й расположе¬
н ы в заголовочном ф а й л е s t d l i b . h .
Например:
i n t *pIntBuffer;
// Выделение пам ти под 5 переменных типа i n t
pIntBuffer=malloc(5*sizeof(int));
П р и отсутствии требуемого количества памяти ф у н к ц и я malloc воз¬
вращает значение n u l l .
Выделение динамической памяти также м о ж н о выполнять операто
р о м new, а освобождение — оператором delete. Оператор new автоматиче
ски учитывает тип объекта и выделяет требуемое количество памяти.
Пример:
double *pBuffer;
// Выделение пам ти под 5 переменных типа double
pBuffer=new double [10];
117
Курс
Введение в программирование
Лекция 13. Java. Механизмы наследования.
Ссылочные типы данных. Интерфейсы.
Вложенные классы
Механизмы наследования
Класс — это шаблон, в котором определяются д а н н ы е и поведение
объекта. Объекты одного класса совместно используют общую структуру
данных и общее поведение.
Объявление класса в я з ы к е Java создает новый ссылочный т и п , опре
д е л я ю щ и й к а к описание методов, так и их реализацию.
Объявление интерфейса создает н о в ы й ссылочный т и п , который
специфицирует описание методов и имена некоторых констант, н о н е оп¬
ределяет саму их реализацию.
Интерфейс может быть объявлен для р а с ш и р е н и я одного или не¬
скольких интерфейсов.
Наследование позволяет определять новые классы в терминах суще
ствующих классов. В я з ы к е Java поддерживается только простое наследо
вание: любой подкласс является производным только от одного н е п о
средственного суперкласса. П р и этом любой класс может наследоваться
от нескольких интерфейсов.
Наследование интерфейсов реализует некоторую замену множест¬
венному наследованию, когда вместо того чтобы один класс имел не¬
сколько непосредственных суперклассов, этот класс наследует несколько
интерфейсов. И н т е р ф е й с позволяет определить некоторый шаблон клас¬
са: описание методов без их реализации.
Я з ы к Java разрешает несколько уровней наследования, определяе¬
мых непосредственным суперклассом и косвенными суперклассами. На¬
следование м о ж н о использовать для создания иерархии классов.
П р и создании подкласса на основе одного или нескольких супер¬
классов возможны следующие способы изменения поведения и структу¬
р ы класса:
• р а с ш и р е н и е суперкласса путем добавления новых данных и методов;
• замена методов суперкласса путем их переопределения;
• слияние методов и з суперклассов вызовом одноименных методов и з
соответствующих суперклассов.
Объявление класса
Объявление класса вводит новый ссылочный тип и определяет или
часть, или всю его реализацию.
118
Java. Механизмы наследования.
Ссылочные типы данных. Интерфейсы. вложенные классы
Лекция 13
П р и загрузке класса выделяется память для всех его статических п е
ременных, и затем выполняется их и н и ц и а л и з а ц и я .
Объявление класса может иметь следующее формальное описание:
МодификаторыКласса class
Имя Класса
extends ИмяСуперКласса
implements СписокРеализуемыхИнтерфейсов
{ТелоКласса}
Тело класса содержит описание переменных, методов и вложенных
классов и заключается в фигурные скобки. В частном случае тело класса
может н е содержать н и одного объявления.
Например:
p u b l i c c l a s s A implements B {
public A() {
}
p u b l i c i n t Metod1(){return 0;}
}
interface B {
p u b l i c i n t Metod1();
}
Вложенный класс описывается так ж е , к а к и в н е ш н и й .
В о п и с а н и и каждого класса указывается и м я класса и тело класса,
содержащее объявления полей класса. Дополнительно для класса могут
быть заданы модификаторы класса и указан непосредственный супер¬
класс и реализуемые классом интерфейсы. П о л я м и класса в Java называ
ются переменные и методы, определяемые в теле класса.
Класс может иметь более одного модификатора класса.
В я з ы к е программирования Java существуют следующие модифика¬
торы класса:
• abstract, я в л я ю щ и й с я модификатором реализации класса и опреде
л я ю щ и й , что класс может иметь абстрактные методы (методы, н е
и м е ю щ и е реализации);
• f i n a l , я в л я ю щ и й с я модификатором ограничения иерархии классов
и указывающий, что класс н е может иметь подклассов (не должен
никогда появляться во фразе extends объявления класса). Класс с м о
дификатором f i n a l обязан реализовать все свои интерфейсы.
• public является модификатором доступа и указывает, что к данному
классу разрешен доступ и з других пакетов. Доступ может быть вы¬
полнен и л и непосредственно указанием квалифицированного име¬
н и класса, и л и с использованием оператора import.
119
Курс
Введение в программирование
Для указания модификаторов класса применяются следующие правила:
• если класс, и м е ю щ и й абстрактные методы, объявлен без м о д и ф и к а
тора abstract, то возникает ошибка к о м п и л я ц и и ;
• для абстрактных классов нельзя создавать экземпляры класса;
• если при объявлении класса н е указан модификатор public, то класс
доступен только внутри своего пакета;
• при к о м п и л я ц и и каждый общедоступный класс всегда записывается
в отдельный файл с расширением . C L A S S . Такой файл называется
модулем компиляции;
• и м я общедоступного класса должно совпадать с именем файла, с о
держащего код класса на я з ы к е Java;
• один модуль к о м п и л я ц и и может содержать только один класс или
интерфейс, и м е ю щ и е модификатор p u b l i c ;
• один модуль к о м п и л я ц и и может одновременно содержать объявле¬
ние общедоступного класса и нескольких интерфейсов или классов,
не имеющих модификатора p u b l i c ;
• один модуль к о м п и л я ц и и н е может одновременно содержать объяв
ление общедоступного класса ( p u b l i c c l a s s ) и общедоступного ин¬
терфейса ( p u b l i c
interface);
• о б ъ я в л е н и е класса о д н о в р е м е н н о с м о д и ф и к а т о р а м и f i n a l и
a b s t r a c t вызывает ошибку к о м п и л я ц и и .
Любой класс может иметь только один суперкласс, указываемый
ключевым словом extends. Наследуемый суперкласс должен быть доступ¬
н ы м классом и н е иметь модификатора f i n a l .
П о умолчанию предполагается, что в том случае, если для класса н е
указано никакого суперкласса, то его непосредственным суперклассом
станет класс Object и з пакета java.lang, который всегда является корневым
классом в любой формируемой иерархии классов.
Раннее и позднее связывание
Раннее и позднее связывание является одним из проявлений п о л и
морфизма, позволяя выполнять одним оператором вызов различных ме¬
тодов в зависимости от типа объекта.
В следующем примере оператор b. M y P r i n t ( ) будет вызывать различ
н ы е методы в зависимости от типа объекта, для которого он выполняется:
c l a s s B{ v o i d MyPrint ( ) {
}}
c l a s s B1 extends B{
v o i d MyPrint ( ) { //Переопределение метода
}
}
120
Java. Механизмы наследования.
Ссылочные типы данных. Интерфейсы. вложенные классы
Лекция 13
c l a s s B2 extends B{
v o i d MyPrint ( ) {
//Переопределение метода
}
}
c l a s s B3 extends B{
v o i d MyPrint ( ) {
//Переопределение метода
}
}
c l a s s PrintB{
B DoBObject ( ) {
B b;
b= new B1();
// Метод, реализующий класс B
b= new B2();
b= new B3();
return b;
}
B b= new PrintB.DoBObject();
b.MyPrint()
// Выполняет вызов метода MyPrint в
// соответствии с типом объекта b
Объявление интерфейса
Объявление интерфейса вводит н о в ы й ссылочный тип, членами к о
торого являются константы и абстрактные методы.
Реализация интерфейса всегда выполняется в классе, который ис¬
пользует д а н н ы й интерфейс.
Один класс может реализовывать несколько интерфейсов, и один
интерфейс может использоваться несколькими классами.
И н т е р ф е й с ы позволяют разделять общую структуру — методы и к о н
станты, классами, не связанными между собой иерархией наследования.
Объявление интерфейса может иметь следующее формальное описание:
МодификаторИнтерфейса ИдентификаторИнтерфейса
дуемыхИнтерфейсов {ТелоИнтерфейса}
extends СписокНасле-
С а м ы м простым примером объявления интерфейса может быть сле¬
д у ю щ и й код:
121
Курс
Введение в программирование
interface
MyColors { i n t RED = 1, YELLOW = 2, BLUE = 4; }
Интерфейс может иметь в качестве предков только интерфейсы.
Интерфейс может иметь модификаторы p u b l i c и abstract. Я з ы к Java
подразумевает, что каждый интерфейс по умолчанию имеет модификатор
a b s t r a c t , который н е рекомендуется указывать я в н о .
К интерфейсу, объявленному с модификатором доступа p u b l i c , мо¬
жет быть произведен доступ из других пакетов, в противном случае —
только из своего пакета.
Тело интерфейса заключается в фигурные скобки и н е может содер¬
жать конструктор или блок и н и ц и а л и з а ц и и статических переменных. В
остальном тело конструктора идентично телу абстрактного класса.
Любая переменная интерфейса п о умолчанию считается перемен
ной с модификаторами p u b l i c , s t a t i c и f i n a l и обязательно должна быть
инициализирована константным выражением. Также каждая переменная
в теле интерфейса н е я в н о считается переменной с модификатором.
Метод, объявленный в теле интерфейса, по умолчанию считается мето
дом с модификаторами abst ract и public. Объявление метода завершается точ
кой с запятой и не содержит тела метода, заключенного в фигурные скобки.
Метод интерфейса н е может иметь модификаторов f i n a l или s t a t i c .
Интерфейс м о ж н о использовать к а к ссылочный тип при объявлении
переменных. Переменная или выражение типа интерфейса могут ссы
латься на любой объект, который является экземпляром класса, реализу¬
ющего д а н н ы й интерфейс. Переменную типа интерфейса м о ж н о исполь¬
зовать только после присвоения ей ссылки на объект ссылочного типа,
для которого был реализован д а н н ы й интерфейс.
Вложенные классы
Проблемы, в о з н и к а ю щ и е из-за отсутствия множественного насле
дования, частично м о ж н о решить с использованием вложенных классов.
Если требуется, чтобы класс ClassA наследовал все доступные мето
ды, включая и protected-методы, двух классов (класса ClassB и класса
ClassC), то реализовать такую схему м о ж н о через вложенный класс.
Класс ClassA создается производным от класса ClassB. Это позволит
всем экземплярам класса ClassA вызывать protected-методы класса ClassB.
В классе ClassA объявляется подкласс ClassFromC, производный от
класса ClassC и переопределяющий все protected-методы класса ClassC,
реализуя их к а к вызовы соответствующих методов из суперкласса.
П р и такой реализации экземпляр класса ClassA получает доступ к
protected-методам двух различных классов — своего суперкласса и своего
вложенного класса.
122
Лекция 13
Java. Механизмы наследования.
Ссылочные типы данных. Интерфейсы. вложенные классы
Абстрактные классы
Абстрактные классы содержат набор методов, который должен быть
реализован в производном классе. Абстрактные классы и абстрактные м е
тоды помечаются модификатором abst ract. Если в подклассе абстрактно
го суперкласса н е выполнена реализация всех абстрактных методов, то
подкласс по умолчанию также является абстрактным.
Приведение ссылочных типов
В я з ы к е Java преобразование ссылочных типов может происходить в
четырех контекстах:
• приведение;
• присваивание;
• вызов метода;
• выполнение арифметических действий.
Наиболее о б щ и м случаем является приведение.
В я з ы к е Java объявление класса определяет о д н о и м е н н ы й ссылоч¬
н ы й тип. Все переменные, и м е ю щ и е ссылочный т и п , указываемый име¬
н е м класса, являются объектами. Тип такого объекта определяется опера¬
тором instanceof.
Например:
String str1;
Object ObjectName;
ObjectName =(Object) s t r 1 ; // Приведение типа
i f (ObjectName i n s t a n c e o f S t r i n g ) {
// Тип объекта S t r i n g
S t r i n g s t r 2 = ( S t r i n g ) ObjectName ;
System.out.println(str2);
// Запись в стандартный поток
// вывода значения строки,
// указанной параметром s t r 2
}
В рассмотренном примере тип объекта s t r 1 сначала приводится к
типу своего косвенного суперкласса Object, а затем оператором instanceof определяется непосредственный тип объекта (при определении опера
тором i n s t a n c e o f типа объекта ObjectName к а к S t r i n g или Object возвраща
ется значение true).
П р и приведении ссылочных типов действуют следующие правила:
• объект всегда может быть приведен к типу своего непосредственно¬
го суперкласса;
123
Курс
Введение в программирование
• приведение ссылочных типов может выполняться по иерархии клас¬
сов сколь угодно глубоко;
• любой класс ссылочного типа всегда м о ж н о привести к типу Object.
После приведения объекта к типу суперкласса все переменные и ме
тоды самого класса объекта становятся недоступными для приведенного
объекта.
Преобразование присвоением происходит в том случае, когда при¬
меняясь к переменной и значению, преобразует значение к типу перемен
ной. П р и преобразовании присвоением не требуется проверки времени
выполнения.
Значение простого типа не может быть присвоено значению ссылоч¬
ного типа, как и значение ссылочного типа не может быть присвоено зна¬
ч е н и ю простого типа.
Присвоение значений ссылочного типа переменным ссылочного ти¬
па не требует во время в ы п о л н е н и я действий преобразования. Просто
компилятор должен иметь возможность преобразовать тип значения вре
мени к о м п и л я ц и и к типу переменной.
Например:
p u b l i c c l a s s A { i n t x, y; }
p u b l i c c l a s s ADerived extends A { i n t z; }
p u b l i c i n t e r f a c e B {void s e t C o l o r ( i n t c o l o r ) ; }
p u b l i c c l a s s AB extends A implements B
{ i n t color;
public void setColor(int color) { t h i s . c o l o r = color; }
}
c l a s s MyA{
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [ ] args) {
// Создание переменных ссылочного типа и присваивание
// им значения:
A p = new A ( ) ;
p = new ADerived();
// Правильно: ADerived это подкласс
// класса A
ADerived p3d = p;
// Ошибка
// Присваивание значени переменной типа Object:
Object o = p;
// Правильно: любой объект приводим
// к типу
Object
i n t [ ] a = new i n t [ 3 ] ;
Object o2 = a;
// Правильно: массив приводим к Object
// Присваивание значени переменной типа интерфейса:
AB cp = new AB();
B c = cp;
// Правильно: AB реализует интерфейс B
124
Лекция 13
Java. Механизмы наследования.
Ссылочные типы данных. Интерфейсы. вложенные классы
// Присваивание значени переменной типа массива:
byte[ ] b = new b y t e [ 4 ] ;
a = b;
// Ошибка: это массивы различных типов
ADerived[ ] p3da = new ADerived[3];
A[ ] pa = p3da;
// Правильно: ADerived подкласс класса A
p3da = pa;
// Ошибка, т. к. необходимо приведение
}
}
Преобразование приведением является более общим: если преобра
зование возможно, то приведение может его выполнить. Часто следует
я в н о указывать преобразование приведением, чтобы компилятор имел
строгую и н ф о р м а ц и ю о типе объекта. Д л я любого типа значения времени
к о м п и л я ц и и всегда м о ж н о выполнить приведение к тому ж е самому типу.
Это позволит точно указать, что результирующее значение будет иметь
и м е н н о указанный тип.
Приведением м о ж н о преобразовывать значения одного вычислимо¬
го типа к другому. Тип boolean н е может быть приведен н и к какому дру¬
гому типу.
Значения простых типов н е могут быть приведены к значениям ссы¬
лочных типов и наоборот.
Эквивалентность объектов
Для определения равенства различных объектов применяется метод
equals.
Метод equals реализован в классе Object и соответственно наследуем
л ю б ы м классом Java. Большинство классов переопределяет этот метод та
к и м образом, что позволяет сравнивать на эквивалентность объекты кон¬
кретного класса.
Например:
class A {
St r i n g objectName;
A ( S t r i n g name) { objectName = name; }
// Конструктор
}
p u b l i c c l a s s MyA {
p u b l i c s t a t i c v o i d main ( S t r i n g args[ ]) {
A A = new A ( " C l a s s 1 " ) ; // Создание экземпляра класса
A A_eq = A; // Ссылка на существующий объект
A A_clon = (A)A.clone;
// Создание объекта методом clone
A A_2 = new A ( " C l a s s 2 " ) ;
125
Курс
Введение в программирование
//
if
if
if
Сравнение объектов:
(A.equals(A_eq))
(A.equals(A_ c l o n ) )
(A.equals(A_ 2 ) )
{
{
{
}
}
}
}
}
Выполнив приведенный пример, м о ж н о увидеть, что эквивалентны¬
ми будут только экземпляр класса и объект, созданный к а к ссылка на д а н
н ы й экземпляр класса. А экземпляр класса и его клон, так ж е к а к и раз
л и ч н ы е экземпляры одного класса, н е совпадают.
Принадлежность объекта к конкретному классу проверяется с п о м о
щью оператора instanseof.
Пакеты к л а с с о в J D K
Инструментальный набор J D K включает утилиты и пакеты классов.
Собственно говоря, все стандартные возможности программирова
н и я на Java базируются на классах этого инструментального набора. J D K
состоит из нескольких отдельных пакетов, иногда называемых библиоте¬
ками. Различные среды программирования, такие к а к JBuilder, предо
ставляют дополнительные пакеты классов.
Среда JBuilder 8 Enterprise полностью поддерживает работу со всеми
классами пакета J D K 1.4.
126
Лекция 14
Java. Члены класса. Статические переменые и методы
Лекция 14. Java. Члены класса.
Статические переменые и методы
Объявление переменных и методов класса
Объявление переменных
В я з ы к е Java при объявлении переменной — указании ее типа и име¬
н и — одновременно м о ж н о выполнить ее и н и ц и а л и з а ц и ю .
Д л я переменной могут быть указаны следующие модификаторы до¬
ступа:
• p u b l i c , или protected, или p r i v a t e , — определяющие область в и д и м о
сти переменной;
• s t a t i c — указывает, что переменная является переменной класса, а
не переменной экземпляра класса;
• f i n a l — запрещает присвоение значений переменной вне тела клас¬
са, в котором о н а объявлена;
• t r a n s i e n t — указывает, что переменная н е является частью постоян
ного состояния объекта;
• v o l a t i l e — определяет возможность асинхронного и з м е н е н и я пере¬
менной.
П е р е м е н н а я , н е и м е ю щ а я модификатора s t a t i c , называется пере
м е н н о й экземпляра. П е р е м е н н а я экземпляра создается для каждого н о
вого экземпляра класса.
Переменная, имеющая модификатор s t a t i c , называется переменной
класса. Для всех экземпляров класса существует только одна переменная
класса. Эта переменная доступна и до создания экземпляра класса.
П е р е м е н н а я , и м е ю щ а я модификатор f i n a l , должна быть и н и ц и а л и
зирована внутри тела класса, так к а к в н е тела класса f i n a l - п е р е м е н н а я
является константой и ее и з м е н е н и е или и н и ц и а л и з а ц и я запрещены.
М о д и ф и к а т о р t r a n s i e n t нельзя использовать совместно с модифи¬
каторами f i n a l или s t a t i c .
Любая переменная может иметь модификатор доступа p u b l i c (обще
доступный), protected ( з а щ и щ е н н ы й ) или p r i v a t e (скрытый).
Д л я этих модификаторов определены следующие правила доступа:
• p u b l i c указывает, что д а н н а я переменная будет доступна везде, где
доступен класс, в котором она объявлена;
• protected указывает, что д а н н а я переменная будет доступна к а к вну
три пакета, содержащего объявление класса, в котором она опреде¬
лена, так и внутри любого подкласса данного класса;
127
Курс
Введение в программирование
• p r i v a t e указывает, что данная переменная н е будет доступна нигде
кроме тела класса, в котором она объявлена.
П о умолчанию переменная считается доступной везде внутри паке
та, содержащего класс, в котором она объявлена, и н е недоступна н и в ка¬
ком другом подклассе указанного класса в том случае, если подкласс со¬
держится в другом пакете.
И н и ц и а л и з а ц и я п е р е м е н н о й означает п р и с в о е н и е этой п е р е м е н
н о й некоторого з н а ч е н и я . В качестве з н а ч е н и я и н и ц и а л и з а ц и и могут
выступать:
• выражение;
• массив, указываемый в фигурных скобках.
Если переменная объявлена с модификатором static, то и н и ц и а л и з а
ц и я выполнятся сразу п р и загрузке класса.
Если объявляемая переменная является переменной экземпляра, то
и н и ц и а л и з а ц и я в ы п о л н я е т с я п р и в ы п о л н е н и и метода-конструктора
класса.
Если объявляемая переменная является локальной переменной, то
ее и н и ц и а л и з а ц и я происходит при выполнении оператора объявления
этой переменной.
Например:
int i1, i2;
f l o a t f1 = 3.0;
f l o a t dArray1 [ ] = new f l o a t [14];
java.lang.String
str1 = "
";
Object oObj = s t r 1 ;
Exception e = new Exception ( ) ;
Определение методов
В я з ы к е Java определение метода включает его объявление и реали
зацию. Определение метода всегда указывается в теле класса.
Метод может иметь модификаторы доступа, возвращать значение и
получать параметры.
Метод может иметь следующие модификаторы:
•
p u b l i c , p r o t e c t e d или p r i v a t e — м о д и ф и к а т о р ы доступа;
• s t a t i c — модификатор метода класса;
• a b s t r a c t , f i n a l , n a t i v e или synchronized.
Д л я м о д и ф и к а т о р о в доступа метода о п р е д е л е н ы следующие пра¬
вила:
• p u b l i c указывает, что д а н н ы й метод будет доступен везде, где досту¬
пен класс, в котором о н определен;
128
Лекция 14
Java. Члены класса. Статические переменые и методы
• p rotected указывает, что д а н н ы й метод будет доступен как внутри па
кета, содержащего объявление класса, в котором о н определен, так и
внутри любого подкласса данного класса;
• p r i v a t e указывает, что д а н н ы й метод не будет доступен нигде кроме
тела класса, в котором о н определен.
П о умолчанию метод считается доступным везде внутри пакета, со¬
держащего класс, в котором о н определен, и недоступным н и в к а к о м
другом подклассе указанного класса в том случае, если подкласс содер¬
жится в другом пакете.
Метод, не и м е ю щ и й модификатора s t a t i c , называется методом э к
земпляра. Метод экземпляра может быть вызван только для созданного
экземпляра класса или подкласса. Такой метод нельзя вызывать н е п о
средственно, квалифицируя его именем класса.
Метод, объявленный с модификатором s t a t i c , называется статичес
к и м методом (или методом класса) и может быть вызван без создания э к
земпляра класса. Этот метод всегда вызывается непосредственно из клас¬
са. Статический метод имеет доступ к другим статическим п е р е м е н н ы м и
методам данного класса.
Если статический метод определен как f i n a l - м е т о д , то он не может
быть переопределен.
Например:
// Файл A.java
package c l a s s a ;
p u b l i c c l a s s A implements B {
p u b l i c A() { }
s t a t i c i n t b=1;
p u b l i c i n t Metod1(){return a;}
p u b l i c s t a t i c i n t Metod2(){return 0;} //Статический метод
}
interface B {
f i n a l p u b l i c s t a t i c i n t a=1;
i n t Metod1();
// Статическая переменная
}
// Файл C.java
package c l a s s a ;
p u b l i c c l a s s C extends A {
p u b l i c C() { }
s t a t i c i n t b=3;
p u b l i c i n t Metod1(){return a;}
p u b l i c s t a t i c i n t Metod2(){return 77;}
p u b l i c s t a t i c v o i d main(Str i n g [ ] a r g s ) {
129
Курс
Введение в программирование
System.out.println(A.Metod2());
System.out.println(C.Metod2());
}
}
П р и переопределении методов их м о д и ф и к а т о р ы доступа д о л ж н ы
совпадать. Так, нельзя переопределить метод, и м е ю щ и й м о д и ф и к а т о р д о
ступа p u b l i c , методом с модификатором доступа p r i v a t e .
Абстрактный метод указывается модификатором a b s t r a c t . Такой
метод никогда н е имеет тела метода: вместо фигурных скобок, ограничи¬
вающих тело метода, объявление метода завершается точкой с запятой.
Абстрактные методы м о ж н о объявлять только в абстрактных классах
или интерфейсах. Объявление абстрактного метода в классе, н е и м е ю щ е м
модификатора a b s t r a c t , приводит к о ш и б к е к о м п и л я ц и и . Л ю б о й под
класс абстрактного класса, который сам н е является абстрактным клас
сом, должен определять реализацию всех наследуемых нереализованных
абстрактных методов.
Например:
p u b l i c c l a s s A extends AA implements B {
public A() { }
p u b l i c i n t Metod1(){return 0;}
p u b l i c s t a t i c i n t Metod2(){return 0;}
i n t Metod3(){return 0;}
p u b l i c i n t Metod4(){return 0;}
}
interface B {
i n t Metod1();
abstract
i n t Metod4();
}
a b s t r a c t c l a s s AA{
abstract
i n t Metod3();
}
Методы, объявленные с модификатором p r i v a t e , н е могут быть абст¬
р а к т н ы м и методами, так к а к они недоступны вне тела класса. Статичес¬
к и е методы также н е могут выступать в качестве абстрактных методов, так
к а к считаются к о н е ч н ы м и и н е могут быть переопределены.
Объявление метода с модификатором f i n a l запрещает его последую
щее переопределение. Такие методы называются к о н е ч н ы м и методами, и
п о умолчанию считается, что p r i v a t e - м е т о д всегда является к о н е ч н ы м
методом.
130
Лекция 14
Java. Члены класса. Статические переменые и методы
Методы, объявленные с модификатором native, могут иметь реали
зацию на другом я з ы к е программирования. Эти методы используются для
н а п и с а н и я м а ш и н н о - з а в и с и м о г о кода. Native-методы в Java-программе
н е имеют тела метода.
Synchronized-методы выполняются с блокировкой: для метода клас
са выполняется блокировка класса; для метода экземпляра — блокировка
объекта.
Это позволяет предотвратить параллельный доступ к д а н н ы м и з раз¬
личных потоков в многопоточном приложении.
Метод может возвращать значение заданного типа. В этом случае:
• перед именем метода указывается т и п возвращаемого значения;
• в теле метода присутствует оператор return, определяющий возвра¬
щаемое значение.
Если метод н е имеет возвращаемого значения, то о н должен быть
объявлен с ключевым словом void, указывающим на отсутствие возвра
щаемого значения.
Если в качестве возвращаемого значения должен быть использован
массив, то после и м е н и метода может быть указана пара квадратных ско¬
бок или с п и с о к параметров и пара квадратных скобок.
Передача параметров
С п и с о к формальных параметров содержит упорядоченные и разде
л е н н ы е запятой о п и с а н и я параметров (тип параметра и идентификатор
параметра). Если метод н е имеет параметров, передаваемых ему п р и вы¬
зове, то после и м е н и метода указывается пара пустых скобок.
В я з ы к е Java все параметры передаются по значению. П р и передаче
параметра ссылочного типа его значением является ссылка на объект, п о
этому в метод передается ссылка на экземпляр класса.
Параметры в я з ы к е Java рассматриваются к а к локальные перемен¬
н ы е метода, с п е ц и ф и ц и р о в а н н ы е вне тела метода. П р и вызове метода пе¬
ред его в ы п о л н е н и е м происходит вычисление в ы р а ж е н и й , представляю¬
щих фактические передаваемые методу параметры, и присвоение вычис¬
л е н н ы х значений соответствующим локальным п е р е м е н н ы м (формаль¬
н ы м параметрам).
Ссылка на текущий объект
П р и вызове метода экземпляра ключевое слово t h i s :
• указывает ссылку на текущий объект. Это может быть использовано
для передачи самого объекта в качестве аргумента методу самого э к
земпляра класса;
131
Курс
Введение в программирование
• используется для указания к в а л и ф и ц и р о в а н н о й ссылки на поля (пе
р е м е н н ы е и методы) экземпляра класса.
Ключевое слово super используется для указания к в а л и ф и ц и р о в а н
ной ссылки на поля (переменные и методы) суперкласса.
П о у м о л ч а н и ю л ю б о й метод п е р в о н а ч а л ь н о ссылается на с в о и
с о б с т в е н н ы е п е р е м е н н ы е и методы, и только в случае их отсутствия в ы
п о л н я е т с я п о и с к этих п о л е й вверх по иерархии суперклассов. П р и
э т о м , если метод н е переопределяется, то его и м я не обязательно к в а
лифицировать.
Например:
class A {
p u b l i c i n t a;
}
c l a s s B extends A {
p u b l i c i n t a, b;
p u b l i c v o i d Metod1 ( ) {
b=a;
// Ссылка на t h i s . a
b=super.a;
}
}
И м я суперкласса может быть использовано для квалифицированно¬
го доступа к статическим п е р е м е н н ы м или методам.
Переопределение метода
Переопределением метода называется объявление в подклассе ме
тода, у которого и м я , тип и с п и с о к параметров, в точности совпадают с
соответствующими атрибутами метода, р а н е е объявленного в супер¬
классе.
П р и переопределении метода использование модификаторов досту¬
па должно удовлетворять следующим условиям:
• если переопределяемый метод суперкласса не содержит н и одного из
модификаторов доступа p u b l i c , protected или p r i v a t e , то переопре
деляющий метод не должен иметь модификатора p r i v a t e .
• если переопределяемый метод суперкласса имеет модификатор д о
ступа p rotected, то переопределяющий метод должен иметь м о д и ф и
катор доступа p u b l i c или protected.
• если переопределяемый метод суперкласса имеет модификатор д о
ступа p u b l i c , то переопределяющий метод должен также иметь мо¬
дификатор доступа p u b l i c .
132
Лекция 14
Java. Члены класса. Статические переменые и методы
Тип возвращаемого значения переопределяющего метода должен
совпадать или преобразовываться присвоением к типу возвращаемого
значения переопределяемого метода.
Если класс содержит переопределяющий метод, то переопределен¬
н ы й метод м о ж н о вызвать только с к в а л и ф и к а ц и е й ссылки ключевым
словом super или именем суперкласса (для статических членов).
Например:
class A
{
p u b l i c v o i d Metod1() { }
p u b l i c s t a t i c v o i d Metod2() { }
}
c l a s s B extends A {
p u b l i c Metod1() {
}
Metod1();
// Вызов метода из класса B
super.Metod1();
// Вызов метода из класса A
A.Metod2();
}
Перегружаемые методы
Перегружаемыми методами называется группа методов с одинако
вым именем, н о различными списками параметров. Я з ы к Java позволяет
определять в классах перегружаемые методы.
Конструкторы
Конструктором называется метод, вызываемый для и н и ц и а л и з а ц и и
объекта п р и его создании.
И м я к о н с т р у к т о р а всегда с о в п а д а е т с и м е н е м к л а с с а . К о н с т р у к
тор не может использовать оператор return и для него не указывается
никакого типа возвращаемого значения. П р и объявлении конструк
тора можно указать модификаторы доступа p u b l i c , protected или
private.
Наличие я в н о описанного конструктора в классе н е является обяза
тельным. В этом случае п р и создании объекта используется конструктор
по умолчанию. Такой конструктор н е получает параметров и вызывает н е
посредственно конструктор суперкласса: s u p e r ( ) .
П р и этом, если суперкласс н е имеет конструктора без списка пара¬
метров, то происходит ошибка к о м п и л я ц и и .
133
Курс
Введение в программирование
Конструкторы не наследуются подклассами.
Тело конструктора заключается в фигурные скобки.
П р и этом первыми операторами д о л ж н ы быть указаны, если они ис¬
пользуются, операторы вызова конструкторов данного класса или супер¬
класса.
Конструктор может иметь следующее формальное описание:
ИмяКласса (СписокПараметров)
ВызовКонструкторов
БлокОператоров
{
}
Вызов конструкторов выполняется операторами t h i s и super с указа¬
н и е м в скобках списка параметров.
Например:
p u b l i c c l a s s C extends A {
p u b l i c C() { t h i s ( 1 , 2 0 ) ; } // Вызов конструктора
// данного класса
public C(int i , i n t j ) { }
}
Вызов конструкторов подчиняется следующим правилам:
• при создании объекта любого заданного класса будет неявно выпол¬
нена цепочка вызовов всех конструкторов его суперклассов;
• первым будет выполнено тело конструктора для Object;
• каждый последующий конструктор в цепочке будет выполняться
только после выполнения конструктора своего непосредственного
суперкласса;
• при создании объекта будут и н и ц и а л и з и р о в а н ы все переменные эк¬
земпляра.
Создание объекта
П р и создании объекта последовательно выполняются следующие
действия: вызывается конструктор, создается н о в ы й объект указанного
типа, и все переменные экземпляра инициализируются своими значени
я м и по умолчанию, затем формируется ссылка на созданный и и н и ц и а л и
зированный объект. Эта ссылка и является значением выражения, созда¬
ющего объект.
Объект может быть создан вызовом метода newInstance. В этом слу
чае используется конструктор без списка параметров.
134
Лекция 14
Java. Члены класса. Статические переменые и методы
Статические переменные
Для каждого класса создается только один экземпляр статической
переменной (переменой класса).
П р и о п и с а н и и статических переменных д о л ж н ы быть в ы п о л н е н ы
следующие правила:
• статические переменные должны быть объявлены вне всякого метода;
• статические переменные могут быть и н и ц и а л и з и р о в а н ы при их объ¬
явлении или блоком кода, отмеченного ключевым словом s t a t i c , и
также р а с п о л о ж е н н ы м вне метода.
И н и ц и а л и з а ц и я статических переменных выполняется при загрузке
класса. И н и ц и а л и з а ц и я переменных выполняется в порядке их следова
н и я в объявлении класса.
Например:
public class C {
p u b l i c C() { }
s t a t i c i n t b=3;
s t a t i c i n t c;
static
{ b++; c = 10; }
// Инициализация статической
// переменной
}
П р и и н и ц и а л и з а ц и и статических переменных м о ж н о вызывать ста¬
тические методы.
135
Курс
Введение в программирование
Лекция 15. С#. Классы и структуры.
Объектные типы
Объектно-ориентированное программирование
на я з ы к е С#
Управляемый код
Я з ы к программирования C# был разработан как я з ы к , использую
щ и й технологию .NET. Поэтому приложение на C# компилируется в п р о
межуточный код, н а з ы в а е м ы й IL-кодом (Intermediate Language) или
M S I L - к о д о м (Microsoft intermediate language). Такой код перед выполне
н и е м компилируется J I T - к о м п и л я т о р о м в команды, отвечающие специ¬
ф и к е конкретного процессора.
В ы п о л н е н и е I L - к о д а управляется м е х а н и з м о м C L R (Common
Language Runtime), непосредственно осуществляющим
JIT-компиляцию
(Just In Time), наложение политик безопасности, предоставление отладоч¬
ных сервисов, автоматическое управление памятью (реализация механиз
ма «сборки мусора»). IL-код можно компилировать как при установке
приложения, так и при его выполнении (при этом компилироваться будет
не весь код, а только реально вызываемые методы). В процессе компиля
ц и и кроме IL-кода формируются также метаданные, описывающие клас
сы. C L R использует метаданные для поиска и загрузки классов, размеще
н и я объектов в памяти, определения входящих в класс методов и свойств.
C L R можно рассматривать как некоторую виртуальную машину, выполня
ющую приложения .NET. Среда C L R обеспечивает единообразное поведе
ние всех приложений вне зависимости от языка реализации кода. CLS-спецификация (Common Language Specification) определяет требования к C L S совместимым я з ы к а м программирования, использующим классы . N E T
Framework как некоторую унифицированную систему типов.
К р о м е создания MSIL-кода, CLS-совместимый компилятор добав
ляет в выходной EXE-файл метаданные, о п и с ы в а ю щ и е используемые т и
п ы и методы. Под метаданными понимаются некоторые д а н н ы е , которые
описывают другие данные. Используя метаданные, среда C L R определя
ет требуемые во время в ы п о л н е н и я т и п ы и методы.
Библиотеки классов . N E T Framework предоставляют большой набор
методов отражения, применяемых средой C L S и другими приложениями
для получения информации о типах и методах, реализуемых приложением.
Отражением называется механизм получения метаданных. A P I отражения
среды . N E T представляет собой иерархию классов System.Reflection.
136
Лекция 15
С#. Классы и структуры. объектные типы
.NETFramework — это та часть платформы .NET, которая предназна
чена для создания надежных, масштабируемых и распределенных п р и л о
ж е н и й , использующих технологии .NET.
.NET Framework состоит из C L R (Common Language Runtime) — сре
д ы времени в ы п о л н е н и я кода, и из набора библиотек классов (иногда на
зываемых B C L — Base Class Library).
П р и л о ж е н и я , в ы п о л н я е м ы е под управлением C L R , называются уп
равляемым кодом.
В Windows в ы п о л н я е м ы м приложением является EXE-файл, библи
отеки реализуются как D L L - ф а й л ы . Технология . N E T предоставляет п р и
ложения в виде сборок, описывающих «логические» E X E - или D L L - ф а й
лы. Сборка содержит декларацию, которая описывает ее содержимое.
Так, сборка m s c o r l i b . d l l содержит все стандартные пространства имен из
пространства имен System для .NET.
Структура приложения на языке С#
Проектом называется совокупность файлов, содержащих информа¬
ц и ю об установках, конфигурации, ресурсах проекта, а также файлов ис¬
ходного кода и заголовочных файлов.
Интегрированная среда проектирования VisualStudio.NET позволяет
для создания проектов на разных языках программирования использо
вать различные инструментальные средства проектирования (например,
Microsoft Visual Basic, Microsoft Visual C#).
Любое приложение на я з ы к е C#, разрабатываемое в среде проекти
рования VisualStudio.NET, реализуется как отдельный проект. П р и л о ж е
н и е на я з ы к е С # может состоять из нескольких модулей. К а ж д ы й модуль
C# может содержать код нескольких классов (при создании приложения
в среде Visual Studio.NET каждый класс C# автоматически помещается в
отдельный модудь — файл с расщирением cs). Среда Visual Studio 2005
позволяет создавать частичные классы ( p a r t i a l c l a s s ) , когда один класс
содержится в нескольких файлах. Соединение всех частей класса выпол
няется на этапе к о м п и л я ц и и . (Вообще, частичными также могут быть
структуры и интерфейсы.)
Для консольного приложения один из классов, реализуемых моду
лем, должен содержать метод M a i n . В я з ы к е C# нет аппарата заголовоч
ных файлов, используемого в я з ы к е С + + , поэтому код модуля должен с о
держать как объявление, так и реализацию класса.
П о умолчанию весь код класса, представляющего консольное п р и
ложение, заключается в одно пространство и м е н , одноименное с именем
приложения.
Точкой входа в программу на я з ы к е C# является метод M a i n .
137
Курс
Введение в программирование
Этот метод может записываться к а к без параметров, так и с одним
параметром типа st ring — указателем на массив строк, который содержит
значения параметров, введенных при запуске программы. В отличие от
списка параметров, задаваемых при запуске С - п р и л о ж е н и я , список пара
метров C # - п р и л о ж е н и я н е содержит в качестве первого параметра и м я
самого приложения.
Код метода указывается внутри фигурных скобок:
s t a t i c v o i d M a i n ( s t r i n g [ ] args)
{
}
Ключевое слово s t a t i c определяет, что метод M a i n является статиче
с к и м методом, вызываемым без создания экземпляра объекта типа клас¬
са, в котором этот метод определен.
Метод, не возвращающий никакого значения, указывается с ключе
вым словом void. Однако, метод M a i n может возвращать значение типа i n t .
Например:
s t a t i c i n t M a i n ( s t r i n g [ ] args)
{
// Проверка числа введенных параметров
i f (args.Length == 0)
{ Console.WriteLine("Нет параметров");
return 1; }
// Для получения значения параметра как значения типа long
// используется функция
Parse
long num = Int64.Parse(args[0]);
// Тип long языка C# является псевдонимом типа Int64.
// Поэтому предыдущая запись эквивалентна записи
// long num = l o n g . P a r s e ( a r g s [ 0 ] ) ;
// Дл получени значени параметра как значени
// определенного типа также можно использовать
// метод ToInt64 класса Convert
long num = Convert.ToInt64(s);
}
К о м п и л я т о р C# допускает наличие метода M a i n сразу в нескольких
классах. Н о для успешной к о м п и л я ц и и и в ы п о л н е н и я такого приложения
следует указать класс, метод M a i n которого следует считать точкой входа
в приложение. Это м о ж н о сделать, установив о п ц и и проекта или указав
о п ц и ю компилятора /main с именем класса, чей метод M a i n будет задей
ствован (например: csc c l a s s 1 . cs c l a s s 2 . cs /main: Class2).
138
Лекция 15
С#. Классы и структуры. объектные типы
Д л я того чтобы установить о п ц и ю проекта, определяющую «старто
вый» класс (Startup Object), следует открыть диалог свойств проекта
Property Pages, в секции Common Properties на странице General выбрать
о п ц и ю Startup Object и указать для нее и м я «стартового» класса (рис. 1).
ConsoleApplicdtion2 Property Pages
Configuration:
^
Configuration M a n a g e r . .
|N/A
|N/A
Common Properties
В
Api
General
Assembly Name
Co ns ole Application2
Designer Defaults
Output Type
Console Application
Default Namespace
ConsoleApplication2
startup Object
ConsoleApplicatiori2.Classl
Application Icon
App.ico
References Path
Г" 1 Configuration Properties
•
ИРгфсТПе^
•
ConsoleApplication2.csproi
Project Folder
C:'(C#_Prujei:t\CijnsoleAppliLatiun2\
ConsoleApplication2.exe
Щ Output File
Wrapper Assembly Key File
Wrapper Assembly Key Name
Startup Object
The name of the class that contains the Main method that you want called on
program startup. The (Not set) option is valid if there is only one Main
I
Отмена
|
Справка
Рис. 1. Определение и м е н и «стартового класса»
Комментарии в программе на языке C#
К о м м е н т а р и й в я з ы к е С # может быть к а к однострочным, т а к и мно¬
гострочным.
Однострочный комментарий может размещаться в начале строки
или после некоторого кода. О н начинается символами // и завершается
к о н ц о м строки.
Многострочный комментарий располагается между парами с и м в о
лов /* и */ .
К о м м е н т а р и й , вставляемый средой проектирования, например //
TODO: Add code t o s t a r t a p p l i c a t i o n here указывает место, в которое д о л
ж е н быть вставлен код, в ы п о л н я е м ы й п р и запуске приложения.
Существует особый т и п комментария, который записывается в sum
mary-секции:
///
<summary> - /// </summary>.
Такой комментарий может быть использован для автоматического
документирования приложения.
139
Курс
Введение в программирование
П р и автоматическом д о к у м е н т и р о в а н и и п р и л о ж е н и я создается
X M L - ф а й л , представляющий собой и н ф о р м а ц и ю о приложении как н е
которую иерархию секций. Для того чтобы при к о м п и л я ц и и приложения
создавался X M L - ф а й л документа, следует установить о п ц и и к о м п и л я ц и и
следующим образом: в о к н е Solution Explorer выделить секцию с именем
проекта и выполнить команду м е н ю View|Property Pages (или Shift+F4), а
затем, выбрав папку Configuration Properties и страницу свойств Build, ус¬
тановить новое значение свойства X M L Documentation File, описываю¬
щее имя файла, в котором будет сохранен XML-документ.
Пространство имен
Пространство имен позволяет именовать группу данных, таких как
классы, переменные и / и л и методы. В я з ы к е C# все библиотеки классов
подключаются как пространства имен.
П р и а в т о м а т и ч е с к о м ф о р м и р о в а н и и п р о е к т а в среде Visual
Studio.NET первой строкой создаваемого приложения вставляется строка
using System.
Ключевое слово using подключает библиотеку классов System (каж¬
дая библиотека классов рассматривается как пространство имен).
Создание пространства и м е н указывается ключевым словом
namespace.
Объявляемые пространства и м е н могут использоваться для структу
рирования программы.
Например:
namespace NameSN1.NameSN2
{
c l a s s A {}
}
namespace NameSN3
{
using NameSN1.NameSN2;
c l a s s B: A {}
}
В среде проектирования Visual Studio.NET библиотеки классов N E T
Framework образуют иерархическую структуру пространств имен.
Библиотеку классов среды . N E T Framework иногда называют N E T
Framework-библиотекой или просто Framework-библиотекой.
Объявление пространства и м е н имеет следующее формальное опи¬
сание:
140
Лекция 15
С#. Классы и структуры. объектные типы
namespace name[.name1] . . . ] {
// объявляемые_данные
}
Пространство и м е н указывается идентификатором, который может
содержать операцию . , определяющую составное имя пространства
имен.
Объявляемыми д а н н ы м и пространства имен могут быть:
• другие пространства имен;
• классы;
• интерфейсы;
• структуры;
• перечисления.
Для того чтобы иметь возможность обращаться к переменным или
методам из пространства и м е н , м о ж н о использовать один из следующих
способов:
• имя соответствующей переменной или метода должно быть квали¬
ф и ц и р о в а н о названием пространства имен (пространство и м е н ука¬
зывается перед именем через точку).
Например:
System.Console.WriteLine("Печать строки");
• имя библиотеки должно быть установлено как доступное операто¬
р о м using.
Например:
using System;
Директива using может использоваться для:
• подключения пространства имен. Класс не может быть подключен
директивой using;
• создания псевдонима и м е н и класса. Псевдоним используется в п р о
грамме для к в а л и ф и к а ц и и членов данного класса.
Объявление псевдонима имеет следующее формальное описание:
using alias=class_name;
Например:
using System.Console = my_SN;
c l a s s MyClass {
141
Курс
Введение в программирование
p u b l i c s t a t i c v o i d Main() {
my_SN.WriteLine("123");}
}
Директива using позволяет не квалифицировать каждую переменную
пространством имен, а просто подключить требуемое пространство имен.
Пространство имен System
Библиотека классов . N E T Framework среды Visual Studio.NET состо¬
ит из иерархически организованного набора пространства имен. В каж¬
дом пространстве и м е н определяется набор типов (классы, структуры,
нумераторы, интерфейсы). Пространство и м е н System содержит набор
классов для общеиспользуемых значений и ссылочных типов данных, с о
бытий и обработчиков событий, интерфейсов, атрибутов и т.п. Также это
пространство и м е н содержит классы, позволяющие выполнять преобра¬
зование типов, реализовывать операции ввода/вывода и т.п.
Все встроенные т и п ы данных я з ы к а C# реализованы как классы
пространства имен. Пространство и м е н System включает такие классы,
как Console, S t r i n g , Array, Math, Boolean, Byte, Char, DateTime, Decimal,
Double, Int16, Int32, Void и т.п.
Псевдонимы типов языка C# и соответствующие им предопределен
н ы е т и п ы пространства и м е н являются при н а п и с а н и и программы взаи
мозаменяемыми.
Д л я о п р е д е л е н и я т и п а п е р е м е н н о й м о ж н о использовать метод
GetType или оператор typeof.
Библиотека классов N E T Framework предоставляет для реализации
потоков ввода, вывода и о ш и б о к класс Console, располагаемый в прост¬
ранстве и м е н System.
Класс Console имеет следующие свойства, о п и с ы в а ю щ и е соответст¬
вующие потоки ввода/вывода:
• In — стандартный поток ввода;
• Out — стандартный поток вывода;
• E r r o r — стандартный поток вывода ошибок.
Класс Console содержит следующие методы, позволяющие осуще
ствлять чтение и запись символов из потоков ввода/вывода:
• Read — чтение символов из потока ввода;
• ReadLine — чтение строки символов из потока ввода;
• Wr i te — запись строки символов в поток вывода;
• Wr i teL i ne — запись в поток вывода строки символа, ограниченной
символами конца строки.
Работа с различными видами коллекций реализуется такими класса¬
ми пространства и м е н System.Collections, как:
142
Лекция 15
С#. Классы и структуры. объектные типы
• A r r a y L i s t — динамически р а с ш и р я е м ы й массив;
• B i t A r r a y — структура данных, каждый элемент которой реализуется
как битовое значение;
• Hashtable — коллекция связанных ключей и значений;
• S o r t e d L i s t — массив, состоящий из пар «ключ—значение»;
• Queue — очередь;
• Stack — коллекция объектов, реализуемая как стек.
Создание классов
Объявление класса
В я з ы к е С # определение класса не обязательно должно иметь мето
д ы конструктор и деструктор.
Управляемый код на я з ы к е С # избавлен от необходимости освобож
дения памяти, выделяемой под объекты, так как это реализуется средой
N E T Framework. Поэтому основное назначение деструктора в я з ы к е C# —
это освобождение неуправляемых ресурсов, таких как окна, файлы, сете
вые соединения и т.п.
Я з ы к C# поддерживает три типа конструкторов:
• конструктор экземпляра объекта (instance), используемый при созда¬
н и и объекта;
• private-конструктор, указываемый в коде для предотвращения автома
тического создания конструктора по умолчанию. Такой тип конструк
тора используется для классов, имеющих только статические члены.
Экземпляр объекта с private-конструктором не может быть создан.
• статический конструктор ( s t a t i c ) , вызываемый для и н и ц и а л и з а ц и и
класса до создания первого объекта или до первого вызова статичес¬
кого метода. Статический конструктор не может иметь модификато¬
р ы доступа и список параметров.
Конструктор э к з е м п л я р а объекта имеет следующее ф о р м а л ь н о е
описание:
[атри буты] [модификаторы_доступа]
имя_деструктора([список_формальных_параметров])
[:base (список_аргументов) | : t h i s (список_аргументов)]
{ тело_конструктора }
Ключевое слово base определяет я в н ы й вызов конструктора базово¬
го класса, а ключевое слово t h i s — вызов конструктора данного класса с
указанным списком параметров.
143
Курс
Введение в программирование
Например:
p u b l i c c l a s s AClass1
{
p u b l i c A C l a s s 1 ( ) / / Объявление конструктора
{
}
}
Ключевое слово class определяет и м я объявляемого класса. Тело
объявляемого класса указывается в фигурных скобках.
Ключевое слово public — это модификатор доступа, указывающий,
что объявляемые после него идентификаторы (имена классов или мето
дов) будут общедоступны (модификатор доступа позволяет определить
область видимости переменных и методов — членов класса).
П о умолчанию все переменные и методы — ч л е н ы класса, заданные
без модификатора доступа, считаются p r i v a t e - п е р е м е н н ы м и (называе¬
м ы м и иногда приватными или закрытыми). П р и в а т н ы е переменные до¬
ступны только внутри экземпляра класса и не могут быть использованы
во внешних функциях модуля.
Модификаторы доступа
В я з ы к е C# применяются следующие модификаторы доступа:
public — доступ не ограничен;
protected — доступ ограничен только наследуемыми классами;
internal — доступ ограничен рамками текущего проекта;
private — доступ ограничен рамками данного класса.
Для любого члена класса или объектного типа разрешено указывать
только один модификатор доступа, за исключением к о м б и н а ц и и protect¬
ed internal, регламентирующей ограничение доступа наследуемыми клас¬
сами текущего проекта.
Например:
•
•
•
•
class A
{
p r o t e c t e d i n t x = 100;
}
class B : A
{
v o i d M1()
144
Лекция 15
С#. Классы и структуры. объектные типы
{
A a1 =
B b1 =
// a1.x
b1.x =
new A ( ) ; // Создание объекта типа A
new B(); // Создание объекта типа B
= 200;
- доступ не разрешен
200;
// Правильно реализованный доступ
}
}
Отметим, что пространство и м е н н е может иметь модификатора до¬
ступа.
Я з ы к C# поддерживает использование вложенных классов.
Типы верхнего уровня, которые не являются вложенными в другие ти¬
пы, могут иметь модификатор доступа только internal (по умолчанию) или
public.
Если модификатор доступа н е указан, то применяется доступ по
умолчанию. В следующей таблице отображены модификаторы доступа
для вложенных типов, являющихся членами других типов.
Член,
определяемый в:
Модификатор доступа,
используемый
по умолчанию
Допустимые
модификаторы доступа
для членов
enum
Public
-
class
private
public
protected
internal
private
protected i n t e r n a l
interface
public
-
struct
private
public
internal
private
Структуры н е могут
иметь модификатор
доступа protected,
так к а к н е могут быть
наследуемы
Например:
using System;
namespace MyNameSpace
{
public class A
145
Курс
Введение в программирование
{
p u b l i c s t a t i c i n t myPublicInt;
i n t e r n a l s t a t i c i n t myInternalInt;
p r i v a t e s t a t i c i n t myPr i v a t e I n t = 0;
p u b l i c c l a s s Nest1
// "Вложенный" член класса
{
p u b l i c s t a t i c i n t myPublicInt;
i n t e r n a l s t a t i c i n t myInternalInt;
pr i v a t e s t a t i c i n t m y P r i v a t e I n t = 0;
}
p r i v a t e c l a s s Nest2
// "Вложенный" член класса
{
p u b l i c s t a t i c i n t m y P u b l i c I n t = 0;
i n t e r n a l s t a t i c i n t m y I n t e r n a l I n t = 0;
pr i v a t e s t a t i c i n t m y P r i v a t e I n t = 0;
}
}
p u b l i c c l a s s MyClass
{
public s t a t i c
i n t Main()
{
// Доступ к членам класса A:
A.myPublicInt = 1; // Доступ не ограничен
A.myInternalInt = 2; // Только в текущем проекте
// A.myPrivateInt = 3; - ошибка: нет
// доступа вне класса
// Доступ к членам класса Nest1 :
A.Nest1.myPublicInt = 1; // Доступ не ограничен
A.Nest1.myInternalInt = 2;
// Только в текущем проекте
// A.Nest1.myPrivateInt = 3; - ошибка: нет
// доступа вне класса Nest1
// Доступ к членам класса Nest2:
// A.Nest2.myPublicInt = 1;
- ошибка: нет
// доступа вне класса A
// A.Nest2.myInternalInt = 2; - ошибка: нет
// доступа вне класса A
// A.Nest2.myPrivateInt = 3; - ошибка: нет
// доступа вне класса Nest2
return 0;
}
146
Лекция 15
С#. Классы и структуры. объектные типы
}
}
Создание экземпляра класса
Для использования переменных и л и методов класса следует создать
объект — экземпляр класса.
В я з ы к е C# экземпляр класса всегда создается при п о м о щ и операто
ра new. Если класс имеет несколько конструкторов, то при создании пере
м е н н о й указывается требуемый конструктор.
Место выделения памяти п о д объект зависит от типа создаваемого
объекта: объекты ссылочных типов размещаются в куче, а объекты раз¬
мерных типов — в стеке.
Объявление переменной объектного типа в я з ы к е С # н е создает объ
екта, а только определяет идентификатор указанного типа. Обратите в н и
м а н и е , что во многих объектно-ориентированных языках, таких как С + + ,
объявление переменной объектного типа также становится и созданием
экземпляра данного типа.
Например:
u s i n g System;
namespace MyNS
{
public class A
{ public A()
// Конструктор без параметров
{ Console.WriteLine("A()");
}
p u b l i c A( i n t i )
// Конструктор с одним параметром
{ C o n s o l e . W r i t e ( " A ( i ) i= " ) ;
Console.WriteLine(i); }
}
}
u s i n g System;
namespace MyNS
{
c l a s s MyClass
{
s t a t i c void M a i n ( s t r i n g [ ] args)
{ A acl1= new A();
// Создание экземпляра класса
A acl2= new A(987);
}
}
}
147
Курс
Введение в программирование
Явный вызов конструктора
Определение конструктора может содержать я в н ы й вызов конструк
тора того ж е класса. Вызываемый конструктор указывается после и м е н и
определяемого конструктора со списком параметров через символ двое
точия. Вызываемый конструктор может быть определен ключевым сло
вом t h i s — для вызова конструктора из того ж е самого класса, или ключе
в ы м словом base — для вызова конструктора базового класса. Я в н о в ы з ы
ваемый конструктор будет выполнен до в ы п о л н е н и я конструктора, в к о
тором он указывается.
Например:
public class A
{ public A():this(222)
{ }
// Конструктор без параметров
p u b l i c A( i n t i ) // Конструктор с одним параметром
{ }
}
Методы члены класса
Среда проектирования Visual Studio . N E T дает возможность исполь
зовать мастер создания метода — члена класса (в о к н е Class View выбрать
и м я класса и выполнить команду контекстного меню Add|Add Metod).
С п и с о к Modifier диалога C# Metod Wizard позволяет указать один из сле¬
дующих модификаторов параметра метода:
• none — определяет передачу параметров по значению. Если внутри
метода будет изменено значение фактического параметра, то вне ме¬
тода его значение останется п р е ж н и м ;
• r e f — определяет передачу параметров по ссылке. И з м е н е н и е пара
метра внутри метода останется и после завершения метода. r e f - п а р а
метр перед использованием обязательно должен быть инициализи¬
рован;
• out — определяет передачу параметров по результату. П р и заверше¬
н и и метода конечное значение формального параметра присваива¬
ется указанному при вызове фактическому параметру. П р и этом в
момент вызова метода фактический параметр может не быть иници¬
ализирован.
Например:
p u b l i c v o i d Metod1(int i , r e f i n t j , out i n t k)
{
}
148
Лекция 15
С#. Классы и структуры. объектные типы
П р и обращении к методу или полю — членам класса используется
операция . (точка) — доступ к члену класса. И м я поля или метода члена
класса квалифицируется именем экземпляра класса.
Я з ы к C# позволяет использовать методы с п е р е м е н н ы м числом п а
раметров. Д л я метода с переменным числом параметров д о л ж н ы быть вы¬
п о л н е н ы следующие правила:
• переменный список параметров выступает к а к единый параметр и
указывается ключевым словом params;
• кроме переменного списка параметров, никаких других параметров
после ключевого слова params в методе указывать нельзя;
• в методе может быть указано только одно ключевое слово params, о п
ределяющее переменный список параметров.
Количество параметров в переменном списке параметров определя
ется свойством Length.
Например:
using System;
p u b l i c c l a s s MyClass1
{
p u b l i c s t a t i c v o i d UseParams1(params i n t [ ]
list)
{
// Отображение списка параметров
f o r ( i n t i = 0 ; i < l i s t . L e n g t h ; i++ )
Console.WriteLine(list[i]);
}
p u b l i c s t a t i c void UseParams2(params object[] l i s t )
{
// В переменном списке параметров могут быть
// объекты различных типов
f o r ( i n t i = 0 ; i < l i s t . L e n g t h ; i++ )
Console.WriteLine((object)list[i]);
}
p u b l i c s t a t i c v o i d UseParams3(int k,params object[]
{
// В переменный список параметров
// включаются параметры, начиная
// со второго
f o r ( i n t i = 0 ; i < l i s t . L e n g t h ; i++ )
Console.WriteLine((object)list[i]);
}
public s t a t i c void Main()
{
UseParams1(1, 2, 3, 4,
UseParams1(1, 2);
5);
149
list)
Курс
Введение в программирование
i n t [ ] myarray = new i n t [ 3 ] {1,2,3};
UseParams1(myarray);
UseParams2(111, ' f ' , " s t r i n g " ) ;
UseParams3(111, ' f ' , " s t r i n g " ) ;
}
}
Структуры
Структуры языка C# идентичны классам и представляют п о и м е н о
ванную совокупность компонент, называемых членами или элементами
структуры. Элементом структуры может быть переменная любого допус
тимого типа или ф у н к ц и я .
Однако структура относится к размерному типу, а класс — к ссылоч¬
ному типу.
Под структуру выделяется память, достаточная для размещения всех
элементов структуры.
П р и создании массивов п р и м е н е н и е типа структуры бывает более
э ф ф е к т и в н о , чем п р и м е н е н и е типа класса.
Тип struct является размерным типом, который может содержать
конструкторы, константы, поля, методы, свойства, индексаторы, опера¬
торы и вложенные типы.
Объявление структуры может иметь следующее формальное описа
н и е (необязательные элементы указаны в квадратных скобках):
[атрибуты] ]модификаторы] s t r u c t имя_структуры [:интерфейсы] {
конструктор ( ) {}
тип_элемента_структуры
имя_ элемента1;
тип_элемента_структуры
имя_ элемента2;
тип_элемента_структуры
имя_ элементам;
} [ ;]
// имя_элемента может быть именем переменной или именем функции
Для обращения к отдельным элементам структуры используется
оператор . (точка).
Доступ к элементам структуры может иметь следующее формальное
описание:
s t r u c t имя_структуры {
модификатор тип_элемента элемент_структуры1;
150
Лекция 15
С#. Классы и структуры. объектные типы
модификатор тип_элемента элемент_структуры2;
}
// Объявление переменной типа структуры
имя_структуры имя_переменной_структуры1;
имя_структуры [ ] имя_переменной_структуры2 =
new имя_структуры[размерность];
// Доступ к элементу структуры
имя_переменной_структуры1.элемент_структуры1= значение1;
имя_переменной_структуры2[индекс].элемент_структуры1=значение2;
Например:
/* Данный пример иллюстрирует консольное приложение, позволяющее
добавлять и отображать элементы структуры. Используемый массив
myAB содержит 400 элементов, каждый из которых является структу
рой из двух полей - name и t e l f a x * /
using System;
namespace MyStruct1
{
s t r u c t AddrBookType
{
p u b l i c s t r ing name;
p u b l i c s t r ing t e l f a x ;
}
/* Созданна структура определ ет новый структурный тип
AddrBookType. Элементы структуры объявлены с модификаторами до¬
ступа p u b l i c , так как по умолчанию элементы доступны только внут¬
ри структуры */
c l a s s Class1
{
{
s t a t i c void Main(str i n g [ ] args)
// Создание массива структур
AddrBookType[] myAB= new AddrBookType[400];
char i c o u n t ;
char i l o o p ;
i n t i=0;
i n t j=0;
while (true)
// Запрос кода операции
{Console.Write ( " I n s e r t kod (0 - new record,
1 - show a l l , 2 - e x i t ) : " ) ;
i c o u n t = (char)Console.Read ( ) ;
while (true)
// Чтение потока ввода
{ i l o o p = (char)Console.Read ( ) ;
151
Курс
Введение в программирование
/* Цикл чтения символов будет завершен при
нажатии пользователем клавиши Enter и
получения из потока ввода символа '\n' */
i f ( i l o o p == '\n') break;}
i f ( icount=='2')
break;
switch ( i c o u n t )
{case '0':
C o n s o l e . W r i t e L i n e ( " I n s e r t Name: " ) ;
myAB[ i].name =Console.ReadLine ( ) ;
C o n s o l e . W r i t e L i n e ( " I n s e r t phone : " ) ;
myAB[ i ] . t e l f a x = Console.ReadLine ( ) ;
// Счетчик введенных элементов
break;
case '1':
// Запись в стандартный поток
// вывода
f o r ( j=0; j<i;j++)
{Console.Write(myAB[j].name);
Console.Write(" " ) ;
Console.WriteLine(myAB[j].telfax); }
break;
default :
Console.WriteLine("Ошибка ввода");
break;
}
// Конец switch
}
// Конец w h i l e
}
}
}
Я з ы к C# позволяет создавать п е р е м е н н ы е т и п ы структуры двумя
способами:
• т р а д и ц и о н н ы м способом с п р и м е н е н и е м оператора new — в этом слу
чае объявление п е р е м е н н о й т и п а структуры и д е н т и ч н о объявлению
п е р е м е н н о й типа класса и при о б ъ я в л е н и и п е р е м е н н о й в о з м о ж н а
о д н о в р е м е н н а я и н и ц и а л и з а ц и я полей структуры;
• о б ы ч н ы м объявлением п е р е м е н н о й как для любого размерного типа.
152
Лекция 16
C#. Механизмы наследования. Абстрактные классы. Интерфейсы
Л е к ц и я 16. C # . М е х а н и з м ы н а с л е д о в а н и я .
Абстрактные классы. Интерфейсы
Механизмы наследования
Объявление класса в я з ы к е C# создает н о в ы й ссылочный тип, опре
д е л я ю щ и й к а к описание методов, так и их реализацию.
Объявление интерфейса создает новый ссылочный тип, который
специфицирует описание методов и имена некоторых констант, но не оп¬
ределяет саму реализацию.
Интерфейс может быть объявлен для р а с ш и р е н и я одного или не¬
скольких интерфейсов.
Наследование позволяет определять новые классы в терминах суще
ствующих классов. В я з ы к е C# поддерживается только простое наследо
вание: любой подкласс является производным только от одного н е п о
средственного суперкласса. П р и этом любой класс может наследоваться
от нескольких интерфейсов.
Производные классы
В среде VisualStudio.NET новый производный класс можно создать,
используя окно ClassView (выполнив в нем команду контекстного меню
Add|Add Class). Рисунок 1 иллюстрирует страницы диалога C# Class Wizard,
предлагаемого средой VisualStudio.NET для создания нового класса.
Рис. 1. Диалог C# Class Wizard
153
Курс
Введение в программирование
И м я создаваемого класса указывается в поле Class Name на страни
це Class Options диалога C# Class Wizard.
В поле Namespace указывается пространство и м е н , к которому будет
принадлежать создаваемый класс. П о умолчанию проект размещается в
пространстве и м е н , о д н о и м е н н ы м с именем проекта.
В поле Access выбирается модификатор доступа для создаваемого класса.
Для класса в я з ы к е C# возможно использование двух модификато¬
р о в доступа:
• public — определяет, что нет ограничений на использование класса;
• internal — определяет, что класс будет доступен для файлов, входя¬
щих в ту ж е сборку.
Сборка — это ф и з и ч е с к и й файл, который состоит из нескольких P E файлов (portable executable), генерируемых компилятором среды .NET. В
сборку входит декларация (manifest), содержащая описание сборки для
управляющей среды .NET.
Класс может имеет один из следующих модификаторов класса:
• abstract — определяет, что класс должен быть использован только
как базовый класс других классов. Такие классы называются абст¬
рактными
классами;
• sealed — определяет, что класс нельзя использовать в качестве базо
вого класса. Такие классы в я з ы к е C# иногда называются изолирован¬
ными классами.
Очевидно, что изолированный класс не может быть одновременно и
абстрактным классом.
Объявление класса может иметь следующее формальное описание:
МодификаторДоступа МодификаторКласса c l a s s ИмяКласса
: ИмяНаследуемогоКласса
{ТелоКласса
}
Тело класса содержит описание переменных, методов и вложенных
классов и заключается в фигурные скобки. В частном случае тело класса
может не содержать н и одного объявления.
Например:
namespace CA1
{
public abstract c l a s s Class2
{
public
Class2()
{
154
: CA1.Class1
Лекция 16
C#. Механизмы наследования. Абстрактные классы. Интерфейсы
// TODO: Add c o n s t r u c t o r l o g i c
here
}
}
Методы — члены класса
В среде VisualStudio.NET добавить в класс н о в ы й метод м о ж н о , ис¬
пользуя контекстное меню окна Class View. На рис. 2 приведен диалог C#
MetodWizard, позволяющий определить модификаторы метода и список
формальных параметров.
Рис. 2. Диалог C# MetodWizard
Язык C# поддерживает следующие модификаторы метода члена класса:
• s t a t i c — определяет статический метод, доступный без создания э к
земпляра класса;
• a b s t r a c t — определяет абстрактный метод, который является членом
абстрактного класса;
• v i r t u a l — метод, реализация которого может быть переопределена в
производных классах;
• extern — метод, и м е ю щ и й реализацию вне данного класса (внешний
метод);
• o v e r r i d e — метод, в ы п о л н я ю щ и й переопределение виртуальной
ф у н к ц и и , наследуемой от базового класса;
155
Курс
Введение в программирование
• new — метод, с к р ы в а ю щ и й в производном классе наследуемый метод
с тем же именем (если ключевое слово не указано, то и м я скрывает
ся, но при к о м п и л я ц и и отображается предупреждение warning).
Порядок указания модификаторов доступа и модификаторов метода
несущественен.
Виртуальные и абстрактные методы всегда д о л ж н ы указываться с
модификатором доступа p u b l i c .
Виртуальные методы
Виртуальные методы объявляются в базовом классе с ключевым сло
вом v i r t u a l , а в производном классе могут быть переопределены. Метод,
который переопределяет виртуальный, указывается ключевым словом
o v e r r i d e . Прототипы виртуальных методов как в базовом, так и в произ¬
водном классе д о л ж н ы быть одинаковы.
П р и м е н е н и е виртуальных методов позволяет реализовывать меха
низм позднего связывания.
На этапе к о м п и л я ц и и строится только таблица виртуальных мето
дов, а конкретный адрес проставляется уже на этапе выполнения.
П р и вызове метода — члена класса действуют следующие правила:
• для виртуального метода вызывается метод, соответствующий типу
объекта, на который имеется ссылка;
• для невиртуального метода вызывается метод, соответствующий ти¬
пу самой ссылки.
П р и позднем связывании определение вызываемого метода происхо
дит на этапе в ы п о л н е н и я (а не при к о м п и л я ц и и ) в зависимости от типа
объекта, для которого вызывается виртуальный метод.
П р и раннем связывании определение вызываемого метода происхо
дит на этапе к о м п и л я ц и и .
Например:
using System;
namespace MyDerriv1
{
c l a s s Class1
{
s t a t i c void M a i n ( s t r i n g [ ] args)
{
// Тип объекта и тип ссылки совпадают
CA var1; var1=new CA();
// Вызывается метод класса CA
Console.WriteLine ( v a r 1 . F 1 ( ) ) ;
156
Лекция 16
C#. Механизмы наследования. Абстрактные классы. Интерфейсы
// Вызываетс метод класса CA
Console.WriteLine ( v a r 1 . F 2 ( ) ) ;
// Тип объекта - CB , а тип ссылки - CA
CA var2; var2=new CB();
// Вызываетс метод класса CA
Console.WriteLine ( v a r 2 . F 1 ( ) ) ;
// Вызываетс метод класса CB
Console.WriteLine ( v a r 2 . F 2 ( ) ) ;
}
}
}
// Класс CA
using System;
namespace MyDerriv1
{
p u b l i c c l a s s CA
{ p u b l i c CA()
{
}
p u b l i c i n t F1() { return 1; }
p u b l i c v i r t u a l s t r ing F 2 ( )
{return " Метод F2 класса CA";}
}
}
// Класс CB
using System;
namespace MyDerriv1
{ p u b l i c c l a s s CB : MyDerr iv1.CA
{
p u b l i c CB() {
}
p u b l i c i n t F1() {return 2; }
// Переопределение виртуального метода F2
p u b l i c o v e r r i d e s t r ing F2()
{ return " Метод F2 класса CB"; }
}
}
Абстрактные классы
Абстрактным
классом называется класс, к о т о р ы й содержит о д и н
или несколько абстрактных методов.
Абстрактный класс н е может использоваться для создания объектов.
К а к п р а в и л о , абстрактный класс описывает н е к и й и н т е р ф е й с , кото¬
р ы й д о л ж е н быть р е а л и з о в а н всеми его п р о и з в о д н ы м и классами.
157
Курс
Введение в программирование
Абстрактный метод языка C# не имеет тела метода и аналогичен ч и
сто виртуальному методу я з ы к а C++.
Например:
p u b l i c a b s t r a c t i n t M1(int a, i n t b);
Абстрактный класс м о ж н о использовать только как базовый для дру¬
гих классов. П р и этом если производный класс не содержит реализации
абстрактного метода, то он также является абстрактным классом.
П о у м о л ч а н и ю п р и с о з д а н и и абстрактного класса в среде
VisualStudio . N E T в формируемый абстрактный класс автоматически
вставляется только один метод — конструктор без параметров.
Интерфейсы
Определение интерфейса
В языке C# отсутствует множественное наследование: каждый класс мо
жет иметь только один непосредственный базовый класс. Частичной заменой
множественному наследованию может служить использование интерфейсов.
Интерфейсы могут содержать свойства, методы и индексаторы, но
без их реализации.
Один класс языка C# может наследовать несколько интерфейсов.
В C# интерфейс определяет н о в ы й ссылочный тип, содержащий
объявления методов, которые обязательно д о л ж н ы быть реализованы в
классе, наследующем д а н н ы й интерфейс.
М о ж н о сказать, что интерфейс определяет некоторую модель пове
д е н и я , которая должна быть реализована в любом классе, наследующем
д а н н ы й интерфейс.
Объявление интерфейса может иметь следующее формальное описание:
[атрибуты] [модификаторы]
i n t e r f a c e имя_интерфейса
[:список_базовых_интерфейсов]
{тело_интерфейса}[;]
Например:
i n t e r f a c e IMyInterface: IBase1,
{
i n t M1();
158
IBase2
Лекция 16
C#. Механизмы наследования. Абстрактные классы. Интерфейсы
i n t M2();
}
Если класс, наследующий интерфейс, н е является абстрактным, то
о н обязательно должен реализовать методы, бъявленные в интерфейсе.
П р и наследовании интерфейса абстрактным классом методы, объявлен¬
н ы е в интерфейсе, могут н е иметь реализации только в том случае, если
о н и объявляются с модификатором a b s t r a c t .
Например:
p u b l i c a b s t r a c t c l a s s CMyInterface
: IMyInterface
{
public
CMyInterface()
{
//
}
p u b l i c abstract i n t M1();
p u b l i c abstract i n t M2();
}
i n t e r f a c e IMyInterface
{
i n t M1();
i n t M2();
}
Определение типа объекта
Для получения и н ф о р м а ц и и о том, является л и тип объекта времени
в ы п о л н е н и я совместимым с заданным типом, используется оператор i s .
Если т и п ы совместимы, то оператор возвращает значение true.
Оператор as аналогичен оператору i s , с той л и ш ь р а з н и ц е й , что вы¬
полняет приведение в случае совместимости типов и л и устанавливает
ссылку на несовместимый объект р а в н о й n u l l .
П р и м е н е н и е оператора i s имеет следующее формальное описание:
выражение i s тип.
Например:
s t r i n g s t r 1 = myObjects;
i f ( s t r 1 i s s t r ing)
Console.WriteLine ("тип s t r i n g " ) ;
159
Курс
Введение в программирование
П р и м е н е н и е оператора as имеет следующее формальное описание:
выражение as тип.
Например:
s t r i n g s t r 1 = myObjects as s t r i n g ;
i f ( s t r 1 != n u l l ) Console.WriteLine ( "это строка" );
При этом предыдущая форма записи эквивалентна следующей записи:
выражение as тип ? (тип)выражение
: (тип^П
Приведение типа объекта к типу интерфейса
П р и создании объект сразу м о ж н о приводить к типу интерфейса, ис¬
пользуя оператор as.
Например:
Object i v a r 1 = varb1 as IA;
Если приведение допустимо, то переменная будет содержать ссылку
на интерфейс. Если приведение типа объекта типу интерфейса недопус¬
тимо, то в результате приведения типа переменная примет значение n u l l .
Следующий пример иллюстрирует определение типов объектов и
приведение типа объекта к типу интерфейса.
using System;
namespace MyAClass1
{ c l a s s Class1
{[STAThread]
// Класс
// System.STAThreadAttribute,
// определяющий однопотоковую модель
s t a t i c void Main(str ing[] args)
{
CB varb1 = new CB();
/* Запрос о совместимости типа объекта с типом наследуемого им
интерфейса */
i f (varb1 i s I A )
/* Если переменная типа CB является переменной типа класса, реа
лизующего запрашиваемый интерфейс IA, то оператор i s вернет зна
чение t r u e . */
160
Лекция 16
C#. Механизмы наследования. Абстрактные классы. Интерфейсы
{Console.WriteLine ("varb1 — это ссылка на
класс, который реализует интерфейс IA");}
// Создание объекта типа интерфейса IA
IA ivar=(IA)varb1;
i f ( i v a r i s IA)
{Console.WriteLine ( " i v a r — это ссылка на интерфейс IA");}
bool v a r 1 = i v a r . F 1 ( ) ;
Console.WriteLine("Вызов метода F1 интерфейса IA: {0}",var1);
// Приведение объекта к типу интерфейса
Object i v a r 1 = varb1 as IA;
i f ( i v a r 1 != n u l l )
Console.Wr i t e L i n e ( " i v a r 1 — это ссылка на
интерфейс I A " ) ;
}
}
}
using System;
namespace MyAClass1
{
p u b l i c c l a s s CB : MyAClass1.CA,IA
{ p u b l i c CB()
{ }
p u b l i c bool F1() { return t r u e ; }
p u b l i c i n t F 2 ( i n t a) { return a*10; }
}
i n t e r f a c e IA
{ bool F1();}
}
using System;
namespace MyAClass1
{ p u b l i c a b s t r a c t c l a s s CA
{ p u b l i c CA() { }
public abstract i n t F2(int a);
}
}
Вложенные классы
Я з ы к C# позволяет создавать в л о ж е н н ы е классы. В л о ж е н н ы й класс
объявляется к а к ч л е н другого класса.
Права доступа для вложенного класса могут быть или м е н ь ш и м и ,
или т а к и м и ж е , к а к у содержащего его класса. Так, в л о ж е н н ы й класс н е
может быть о б щ е д о с т у п н ы м , если с о д е р ж а щ и й его класс объявлен к а к
internal.
161
Курс
Введение в программирование
П р и доступе к и м е н и вложенного класса из ч л е н о в в н е ш н е г о класса
к в а л и ф и к а ц и я и м е н е м в н е ш н е г о класса н е требуется.
Например:
using System;
namespace MyNClass1
{ c l a s s Class1
{ s t a t i c v o i d M a i n ( s t r i n g [ ] args)
{ C l a s s 1 . C l a s s 2 var1=
new C l a s s 1 . C l a s s 2 ( ) ; // Эквивалентно
// записи: Class2 var1= new C l a s s 2 ( ) ;
//Вызов метода вложенного класса
Console.Wr i t e L i n e ( v a r 1 . F 1 ( ) ) ;
}
class
Class2
{
p r i v a t e i n t a=12345;
p u b l i c i n t F1() {return t h i s . a ; }
}
}
}
162
Лекция 17
C#. Индексаторы класса и атрибуты
Лекция 17. C#. Индексаторы класса и атрибуты
Индексаторы
Создание индексаторов
Индексатор позволяет работать с классом или структурой таким о б
разом, к а к если бы это были массивы. И н д е к с а ц и я класса выполняется по
индексу, указываемому к а к параметр. Иногда классы, используемые к а к
индексаторы, называют классами-индексаторами.
О б ъ я в л е н и е и н д е к с а т о р а может и м е т ь следующее ф о р м а л ь н о е
описание:
[атрибуты] [модификаторы] тип t h i s [[атрибуты]
тип_параметра идентификатор_параметра
{объявление аксессоров}
]
Индексатор должен иметь к а к м и н и м у м один параметр. Тип и иден¬
тификатор параметра указываются в квадратных скобках после ключево¬
го слова t h i s .
Среда проектирования Visual Studio.NET позволяет использовать ма
стер создания индексатора: для этого в окне Class View следует выделить
имя класса и выполнить команду контекстного меню Add|Add Indexer.
Диалог C# Indexer Wizard (рис. 1) позволяет определить параметры
создаваемого индексатора.
Рис. 1. Диалог C# Indexer Wizard
163
Курс
Введение в программирование
В поле Indexer Acess указывается модификатор доступа для индекса
Это могут быть следующие модификаторы:
p u b l i c — доступ н е ограничен;
p r o t e c t e d — доступ ограничен только наследуемыми классами;
i n t e r n a l — доступ ограничен рамками текущего проекта;
p r i v a t e — доступ ограничен рамками данного класса;
p r o t e c t e d i n t e r n a l — ограничение доступа наследуемыми классами
текущего проекта.
В поле Indexer Type определяется т и п массива, используемого для
индексатора. В качестве типа индексатора может быть выбран любой и з
следующих типов:
тора.
•
•
•
•
•
• bool — логическое з н а ч е н и е t r u e или f a l s e ;
•
•
•
•
•
decimal — 128-битовый т и п данных (1,0 * 1 0 до 7,9 * 10 );
i n t — 32-битовое целочисленное значение;
sbyte — знаковое 8-битовое целое (от — 128 до 127);
u i n t — беззнаковое 32-битовое целочисленное значение (от 0 до 4,
294, 967, 295);
-28
byte;
• double — 64-битовый т и п данных (±5,0 * 1 0
• long — 64-битовое целочисленное значение;
-324
•
•
•
до ± 1 , 7 * 10 );
308
string;
ulong;
char;
• f l o a t — 32-битовый т и п данных (±1.5 * 1 0
•
•
•
28
-45
до ±3.4 * 10 );
38
object;
short;
ushort.
Поле Parameter Name содержит и м я параметра.
На панели Indexer Modifiers можно выбрать одну из следующих опций:
• None — индексатор н е содержит дополнительных модификаторов;
• V i r t u a l — реализация индексатора может быть переопределена в н а
следуемых классах, для индексатора указывается ключевое слово
virtual;
• Abst ract — индексатор является членом абстрактного класса, для и н
дексатора указывается ключевое слово abstract.
Ключевое слово t h i s используется к а к и м я индексатора, так как с
классом, содержащим индексатор, можно манипулировать как с массивом.
Например:
public i n t t h i s [ i n t
{
get
{
i n d 1 ] // Индексатор типа i n t
// с одним параметром типа i n t - ind1
return 0; }
164
Лекция 17
C#. Индексаторы класса и атрибуты
set
{
}
}
Методы-аксессоры
После определения параметра в фигурных скобках указаны два м е тода-аксессора. get-аксессор возвращает значение данных п о указанному
индексу, а set-аксессор устанавливает значение данных с указанным и н
дексом. Устанавливаемое значение задается ключевым словом value.
Индексатор устанавливает и возвращает значения некоторого мас
сива. Такой массив для аксессора должен быть создан. Типы используемо
го массива и аксессора д о л ж н ы совпадать. Н а п р и м е р для целочисленного
аксессора м о ж н о объявить следующий массив:
p r i v a t e i n t [ ] imyArray = new i n t [ 5 0 ] ;
1.
Теперь, чтобы использовать акссессор, следует:
определить возвращаемое методом-аксессором значение
2.
определить устанавливаемое методом-аксессором значение
(например: r e t u r n i m y A r r a y [ i n d 1 ] ; ) ;
(например: imyArray[ ind1]= value; ).
В результате класс, содержащий аксессор, будет иметь следующее
объявление:
p u b l i c c l a s s AClass1
{
public AClass1() { }
p r i v a t e i n t [ ] imyArray = new i n t [ 2 0 ] ;
public i n t t h i s [ i n t ind1]
}
{
get
{ r e t u r n imyArray[ i n d 1 ] ; }
set
{ imyArray[ ind1]= value; }
}
Элементы индексатора
Объект класса, используемого к а к аксессор, создается обычным о б
разом. И н и ц и а л и з а ц и я элементов аксессора указывается к а к присвоение
165
Курс
Введение в программирование
значений элементам массива. Доступ к элементам аксессора записывает¬
ся к а к доступ к элементам массива.
Например:
AClass1 ac1= new A C l a s s 1 ( ) ;
ac1[0]=5;
ac1[1]=6;
Console.WriteLine("ac1[0]= {0}, ac1[1]= {1}",
ac1[0],ac1[1]);
Индексаторы на базе многомерных массивов
Для одного класса может быть создано несколько индексаторов. И н
дексаторы д о л ж н ы различаться числом параметров.
Например:
p u b l i c c l a s s AClass1
{
public AClass1() {
}
p r i v a t e i n t [ ] imyArray = new i n t [ 2 0 ] ;
public i n t t h i s [ i n t ind1]
{ get { return imyArray[ i n d 1 ] ; }
set { imyArray[ ind1]= value; }
}
p r i v a t e i n t [,] imyArray2 = new i n t [ 2 , 1 0 ] ;
public i n t t h i s [ i n t ind1, i n t ind2]
{ get {return imyArray2[ ind1, i n d 2 ] ; }
set { imyArray2[ ind1, ind2]= value; }
}
}
Атрибуты
Язык С# позволяет создавать атрибуты для различных элементов язы
ка, таких как типы, методы, поля и свойства классов. Данные, хранимые в ат
рибутах, можно запрашивать во время выполнения приложения. Атрибуты —
это механизм, позволяющий создавать самоописывающиеся приложения.
Использование атрибутов позволяет получать метаданные периода
выполнения.
К а ж д ы й атрибут — э т о э к з е м п л я р класса, п р о и з в о д н о г о от
System.Attr ibute.
Назначаемый типу или члену класса атрибут указывается в квадрат¬
ных скобках перед типом или членом класса.
166
Лекция 17
C#. Индексаторы класса и атрибуты
П р о атрибут, указанный для класса, иногда говорят, что этот атрибут
«прикреплен к целевому типу».
Класс A t t r i b u t e пространства и м е н System предоставляет следую¬
щ и е ч л е н ы класса:
• GetType — получает объект типа Type текущего экземпляра;
• T o S t r i n g — возвращает строку, описывающую д а н н ы й объект;
• IsDef ined — определяет, существует ли атрибуты заданного типа, на¬
значенные указываемому члена класса;
• GetCustomAttribute — запрашивает атрибут заданного типа для ука¬
занного члена класса.
Для класса A t t r i b u t e определено свойство TypeId, определяющее
уникальный идентификатор атрибута.
Назначение атрибута
Для того, чтобы назначить атрибут элементу кода, можно:
• определить н о в ы й класс атрибута;
• использовать существующий класс атрибута и з библиотеки N E T
Framework.
Атрибут указывается в квадратных скобках перед элементом, кото
рому он назначается. Назначаемый атрибут инициализируется вызовом
конструктора с соответствующими параметрами.
Класс S y s t e m . O b s o l e t e A t t r i b u t e позволяет помечать код и задавать
и н ф о р м а ц и ю , которая будет отображаться к а к Warning во время к о м п и л я
ц и и приложения. Этот класс предназначается для возможности указания
некоторого кода модуля к а к «устаревшего».
Для того чтобы использовать существующий класс для назначаемо¬
го методу атрибута, следует:
1.
создать метод, использующий атрибут (например, метод, п р и каж¬
дом вызове которого компилятор будет формировать сообщение
Warning с указанным в атрибуте кодом);
2.
ввести перед определением метода в квадратных скобках и м я класса
атрибута (например, класса O b s o l e t e A t t r i b u t e ) .
Например:
[ObsoleteAttribute
(«Сообщение, отображаемое
компилятором как Warning»)]
p u b l i c s t a t i c v o i d M1( )
{return ;
// Компилятор будет выдавать предупреждение при
// каждом вызове данного метода, которому назначен
// соответствующий атрибут. Например:
167
Курс
Введение в программирование
// c : \ c # _ p r o j e c t \ p r 1 \ c l a s s 1 . c s ( 2 3 , 4 ) : warning
// CS0618: 'pr1.Class1.M1()' i s o b s o l e t e :
//
'Сообщение, отображаемое компилятором как
//
Warning'
}
Я з ы к С # п р и назначении атрибута позволяет н е указывать суффикс
A t t r i b u t e . Так, вместо [ O b s o l e t e A t t r i b u t e ( " " ) ] м о ж н о з а п и с а т ь
[Obsolete("")].
Класс атрибута должен иметь хотя бы один public-конструктор.
Создание атрибута
Создание атрибута начинается с создания класса, реализующего ат¬
рибут. Такой класс должен быть наследуем от любого класса атрибута.
Класс атрибута всегда должен иметь модификатор доступа p u b l i c .
Класс атрибута всегда непосредственно или опосредованно наследу¬
ется от класса System.Attribute.
Например:
p u b l i c class MyAttribute
: System.Attribute
{
public MyAttribute()
{
}
}
Параметры атрибута
П о умолчанию код класса атрибута содержит конструктор без пара¬
метров.
Для того чтобы иметь возможность п р и назначении атрибута сохра
нять для типа или члена класса некоторые параметры, эти параметры на¬
до задать к а к параметры конструктора класса атрибута. Параметры атри¬
бута могут объявляться к а к переменные члены класса.
Для доступа к з а щ и щ е н н ы м п е р е м е н н ы м членам класса в я з ы к е C#
используются свойства.
Для создания свойства в среде проектирования VisualStudio.NET
м о ж н о использовать мастер построения свойства: для этого в о к н е Class
View следует выделить секцию c именем класса и выполнить команду
контекстного меню Add | Add P rope rty.
В диалоге C# Property Wizard (рис. 2) в поле Property Name следует
указать и м я создаваемого свойства.
168
Лекция 17
C#. Индексаторы класса и атрибуты
ш
[lllllBl
W e l c o m e t o t h e C# A d d P r o p e r t y W i z a r d
T h i s w i z a r d a d d s a p r o p e r t y t o y o u r C# c l a s s .
Property a c c e s s :
Property type:
| public
| BB
1
Property name:
T|
[name
Accessors:
С
get
С
set
(*
get/set
Property modifiers:
t*
None
Г
Static
Г
Virtual
С
Abstract
C o m m e n t (J! notation not r e q u i r e d ) :
1
Finish
|
Cancel
Help
Рис. 2. Диалог C# Property Wizard
Тип создаваемого свойства выбирается из с п и с к а Property type.
Н а панели Accessors переключатели get и set определяют, к а к и е м е т о д ы - а к с е с с о р ы будут созданы. Н а п р и м е р :
using System;
namespace MyPr1
{
[AttributeUsage(AttributeTargets.All)]
public c l a s s MyAttr ibute : System.Attr ibute
{
pr i v a t e s t r i n g name; // Используютс как
p r i v a t e i n t kod;
// параметры атрибута
p u b l i c M y A t t r i b u t e ( s t r ing name)
{ // Конструктор
this.name = name;
t h i s . k o d = 12345;
}
public
// Свойство Name
s t r i n g Name
{ get
{ return name; } }
// Свойство Kod
public
i n t Kod
169
Курс
Введение в программирование
{ get { return kod; }
s e t {kod=value; } // Назначение
// защищенной переменной члену
// класса значени параметра
}
}
}
// Для назначения некоторому классу данного
// атрибута перед объявлением класса следует
// указать строку типа [My("NameClass", Kod=123) ]
Позиционные и именованные параметры атрибута
П р и назначении классу или члену класса атрибута используется кон¬
структор атрибута со списком параметров. Параметры могут быть:
• позиционными;
• именованными.
Позиционные параметры указываются в порядке, который определя
ется списком параметров конструктора атрибута. П о з и ц и о н н ы е парамет¬
р ы всегда д о л ж н ы быть указаны при назначении атрибута.
И м е н о в а н н ы е параметры отсутствуют в списке параметров конст¬
руктора атрибута. Значения, задаваемые для именованных параметров,
используются для и н и ц и а л и з а ц и и полей и свойств создаваемого э к з е м п
ляра атрибута. С п и с о к именованных параметров указывается через запя¬
тую после списка п о з и ц и о н н ы х параметров. Каждый и м е н о в а н н ы й пара¬
метр определяется как Имя_параметра=Значение_параметра.
В предыдущем примере параметр name использовался как позицион¬
н ы й параметр, а kod — как и м е н о в а н н ы й (по умолчанию значение пере¬
м е н н о й kod, доступной через свойство Kod, устанавливается равным к о н
кретному значению. Если при назначении атрибута я в н о не будет задан
и м е н о в а н н ы й параметр, то при создании экземпляра атрибута будет ис¬
пользовано значение по умолчанию).
Параметры атрибута могут указываться константными значениями
следующих типов:
• bool, byte, char, short, i n t , long, f l o a t , double;
• string;
• System.Type;
• enums;
• object (аргумент для параметра атрибута типа object должен быть
константным значением вышеуказанных типов);
• одноразмерные массивы любых вышеуказанных типов.
170
Лекция 17
C#. Индексаторы класса и атрибуты
Используемость атрибута
Атрибуты могут быть использованы для различных элементов языка.
Для того чтобы специфицировать, к а к и м образом и для каких элементов
м о ж н о использовать д а н н ы й класс атрибута, библиотека N E T Framework
предоставляет класс System.AttributeUsageAttribute.
С п е ц и ф и к а ц и я используемости атрибута указывается в квадратных
скобках перед именем определением класса.
Например:
[AttributeUsage(AttributeTargets.All,
Inherited = false,
AllowMultiple = true)]
Элементы языка, которым может быть назначен атрибут, указывают
ся значением или набором значений перечислимого типа Att ributeTargets.
Н а п р и м е р , для использования данного атрибута только для классов
или методов перед определением класса атрибута следует записать:
[AttributeUsage (AttributeTargets.Class
A t t r ibuteTargets.Method)]
|
С п е ц и ф и к а ц и я используемости атрибута имеет следующее фор¬
мальное описание:
[Attr ibuteUsage(
доступные_элементы,
A l l o w M u l t i p l e = t rue_или_false,
Inherited=наследуемость
)]
Доступные элементы определяют те элементы языка, для которых
может быть назначен д а н н ы й атрибут. П о умолчанию используется значе
н и е A t t r i b u t e T a r g e t s . A l l (доступен для всех элементов).
Если и м е н о в а н н ы й параметр A l l o w M u l t i p l e равен t rue, то классу или
члену класса может быть назначено несколько атрибутов.
Параметр I n h e r i t e d определяет, наследуется ли д а н н ы й атрибут про¬
изводным классом (по умолчанию — f a l s e ) .
Перечислимый тип A t t r i b u t e T a r g e t s определяет следующее множе¬
ство значений:
• A l l — все элементы языка;
• Assembly — сборки;
171
Курс
•
•
•
•
•
•
•
•
•
•
•
•
•
Введение в программирование
Class — классы;
Constructor — конструкторы;
Field — поля;
Method — методы;
Property — свойства;
Delegate — делегаты;
Enum — нумераторы;
Event — события;
Interface — интерфейсы;
Module — модули;
Parameter — параметры;
ReturnValue — возвращаемые значения;
Struct — структуры.
Доступ к атрибуту
Значения атрибутов или их существование могут быть з а п р о ш е н ы во
время в ы п о л н е н и я приложения.
П р и запросе для класса или для члена класса д а н н ы х о п р и к р е п л е н
ных к нему атрибутах применяется отражение. Отражением называется
ф у н к ц и я , используемая во время в ы п о л н е н и я приложения для получения
метаданных, в том числе и заданных атрибутами.
Д л я реализации отражения библиотека N E T Framework предостав
ляет несколько классов, базовым для которых служит класс отражения
System.Reflection.
О с н о в н ы е методы о т р а ж е н и я , и с п о л ь з у е м ы е д л я запроса атрибу
тов,
предоставляются
классами
System.Reflection.Memberlnfo
и
System. Reflection.Assembly. Так, метод GetCustomAttributes позволяет оп¬
ределить атрибуты, присущие данному объекту.
Например:
c l a s s MyClass
{
p u b l i c s t a t i c v o i d Main()
{
System.Reflection.MemberInfo i n f o =
typeof(MyClass);
o b j e c t [ ] a t t r = i n f o . GetCustomAttributes(true);
f o r ( i n t i = 0; i < a t t r . L e n g t h ; i ++)
{ System.Console.WriteLine(attr[i]);
}
}
}
172
Лекция 17
C#. Индексаторы класса и атрибуты
В результате в ы п о л н е н и я данного кода в массив будут п о м е щ е н ы
классы
всех
назначенных
атрибутов,
а
также
класс
System.Reflection.DefaultMemberAttribute.
Доступ к типу объекта может быть реализован посредством класса
Type. Метод Obj ect. GetType возвращает объект типа Type, представляющий
тип экземпляра объекта. Объект типа Type представляет собой ассоцииро
в а н н ы й с типом объект, используемый для доступа к метаданным типа.
Используя класс Type, м о ж н о создать объект для типа, экземпляр ко¬
торого еще не был создан.
Например:
Type t= t y p e o f ( M y C l a s s l ) ;
Для создания объекта типа, ассоциированного с типом существую
щего экземпляра объекта, следует использовать метод GetType.
Например:
Type t = obj1.GetType();
, где obj1 экземпляр класса MyClassl.
П р и использовании объекта типа атрибута метод GetCustomAttribute
возвращает значения атрибута, который назначен указанному параметра
ми объекту: первый параметр метода определяет ассоциированный объ
ект, а второй — указывает класс атрибута.
Например:
M y A t t r i b u t e MyAttr =
(MyAttribute) Attribute.GetCustomAttribute(
t,
typeof(MyAttribute));
Следующий пример иллюстрирует доступ к значениям атрибутов.
c l a s s Class1
{ s t a t i c void M a i n ( s t r i n g [ ] args)
{
// Создание объекта, ассоциированного с типом A C l a s s l
Type t= t y p e o f ( A C l a s s 1 ) ;
M y A t t r i b u t e MyAttr =
(MyAttr i b u t e ) A t t r i b u t e . G e t C u s t o m A t t r i b u t e (
t,
typeof
i f ( n u l l == MyAttr)
173
(MyAttr i b u t e ) ) ;
Курс
Введение в программирование
{Console.WriteLine("Атрибут не найден");}
else
{
Console.WriteLine("Атрибут name = {0},
атрибут kod = {1}" ,
MyAttr.Name,
// Возвращает значение
// поля Name атрибута M y A t t r i b u t e
MyAttr.Kod); }
}
}
[Attr ibuteUsage(Attr ibuteTargets.All)]
public c l a s s MyAttribute : System.Attribute
{ pr i v a t e s t r i n g name;
p r i v a t e i n t kod;
p u b l i c MyAttr i b u t e ( s t r i n g name)
{this.name = name; t h i s . k o d = 10; }
public
s t r ing Name { get { return name;} }
public
i n t Kod { get { return kod; }
set {kod=value;
}
}
}
[My("NameOfClass", Kod=123)]
p u b l i c c l a s s AClass1
{ public AClass1() { }
p r i v a t e i n t [ ] i A r r = new i n t [ 1 0 ] ;
public i n t this[ i n t ind1] {
get { return i A r r [ ind1];}
set { i A r r [ ind1]= value; } }
}
Класс Type
Класс System.Type имеет следующее ф о р м а л ь н о е о п и с а н и е :
public abstract
c l a s s Type : MemberInfo, I R e f l e c t .
Д в е с с ы л к и типа Type на объект будут ссылаться на о д и н и тот ж е
объект только в том случае, если о н и представляют о д и н а к о в ы й т и п .
Э к з е м п л я р т и п а Type может быть представлен л ю б ы м и з следующих
типов:
• классы;
• р а з м е р н ы е т и п ы (Value
types);
174
Лекция 17
C#. Индексаторы класса и атрибуты
•
•
•
•
массивы;
интерфейсы;
указатели;
нумераторы.
Ссылка на объект Type, ассоциируемый с типом, может быть получе¬
на одним из следующих способов:
• метод Object.GetType возвращает объект Type, представляющий тип
экземпляра объекта;
• статический метод GetType возвращает объект Type, который пред¬
ставляет тип, указанный посредством своего полного и м е н и ;
• методы Module.GetTypes, Module.GetType, и Module.FindTypes возвра
щают объект Type, который представляет т и п ы , определенные в м о
дуле. Метод GetTypes позволяет получить массив объектов для всех
общедоступных и з а щ и щ е н н ы х типов, определенных в модуле;
• метод FindInterfaces возвращает отфильтрованный с п и с о к интер
фейсов типов, которые поддерживаются д а н н ы м типом;
• метод GetElementType возвращает объект Type, который представляет
элемент;
• методы GetInterfaces и G e t l n t e r f a c e возвращают объект Type, кото
р ы й представляет интерфейс, поддерживаемый типом;
• метод GetTypeArray возвращает массив объектов Type, которые пред
ставляют т и п ы , заданные посредством набора объектов;
• методы GetTypeFromProgID и GetTypeFromCLSID возвращают объект
Type, который указывается через ProgID или CLSID (методы предостав
ляются для совместимости с СОМ);
• метод GetTypeFromHandle возвращает объект Type, который указывается
посредством дескриптора (метод предоставляется для совместимости);
• оператор typeof получает объект Type для указанного типа.
М е т а д а н н ы е — это и н ф о р м а ц и я о в ы п о л н и м о м модуле, получае
мая во в р е м я в ы п о л н е н и я п р и л о ж е н и я . К т а к о й и н ф о р м а ц и и о т н о с я т
с я и д а н н ы е о типе. В случае н е п р а в и л ь н о г о у к а з а н и я и м е н и т и п а воз¬
н и к а е т и с к л ю ч е н и е . П о э т о м у у к а з а н и е т и п а следует заключать в б л о к
try-catch.
Например:
try
{
Type tp=Type.GetType(s);
Console.WriteLine("Имя типа : {0}",tp.FullName);
}
catch
(System.NullReferenceException)
{Console.WriteLine("Ошибка задания типа");}
175
Курс
Введение в программирование
Класс Type предоставляет большой набор свойств для запроса и н
ф о р м а ц и и по типу, включая следующие:
• FullName — возвращает имя типа;
• I s C l a s s — определяет, является ли тип классом;
• I s A b s t r a c t — определяет, является ли тип абстрактным классом;
• IsNestedPublic — определяет, является ли тип вложенным и общедо¬
ступным;
• I s P u b l i c — определяет, является ли д а н н ы й тип общедоступным;
• I s N o t P u b l i c — определяет, является ли д а н н ы й тип з а щ и щ е н н ы м ;
• IsSealed — определяет, является ли тип к о н е ч н ы м (не может быть
базовым классом);
• IsArray — определяет, представляет ли указанный тип массив;
• GUID — возвращает значение типа GUID, ассоциированное с д а н н ы м
типом (такое значение хранится в реестре Windows). Например:
Type myType = typeof(MyClass1);
Guid myGuid =(Guid) myType.GUID;
• IsNestedAssembly — определяет, является ли тип вложенным и види¬
м ы м только в своей собственной сборке;
• Module — возвращает модуль (DLL) в котором объявлен д а н н ы й тип;
• Namespace — возвращает пространство имен, содержащее д а н н ы й
тип.
Свойство IsByRef позволяет определить, передается ли указанный
элемент по типу, а свойство Assembly определяет сборку.
Например:
Type tp=Type.GetType(s);
Console.WriteLine("\tПередается по ссылке ? : {0}",tp.IsByRef);
Получение информации о методах
Используя метод GetMetods, м о ж н о получить и н ф о р м а ц и ю о методах.
Такая и н ф о р м а ц и я заносится в массив типа MetodInf o.
Например:
p u b l i c s t a t i c v o i d Main()
{
Type myType =(typeof(MyClass1));
// Получить методы с доступом p u b l i c
MethodInfo[] myArrMethodInfo =
myType.GetMethods( B i n d i n g F l a g s . P u b l i c
176
Лекция 17
C#. Индексаторы класса и атрибуты
|BindingFlags.Instance
|BindingFlags.DeclaredOnly);
Console.WriteLine("\n Число методов p u b l i c =:"
+myArrMethodInfo. Length);
Console.WriteLine("Имена методов p u b l i c : " ) ;
// Отобразить имена всех методов
MyPr intMethodInfo(myArrMethodInfo);
// Получить методы с защищенным доступом
MethodInfo[] myArrMethodInfo1 =
myType.GetMethods( B i n d i n g F l a g s . N o n P u b l i c
|BindingFlags.Instance
|BindingFlags.DeclaredOnly);
Console.WriteLine("\n Число защищенных методов:"
+myArrMethodInfo1. Length);
}
p u b l i c s t a t i c v o i d MyPrintMethodInfo(MethodInfo[]
{
for(int
i=0;i<a.Length;
{
MethodInfo myMethodInfo = (MethodInfo)a[ i ] ;
C o n s o l e . W r i t e L i n e ( " \ n " + myMethodInfo.Name);
}
}
177
a)
Курс
Введение в программирование
Л е к ц и я 18. C # . О т р а ж е н и я . Д е л е г а т ы
Объявление делегата
Использование делегата для вызова методов
Делегат объявляет н о в ы й ссылочный тип.
Делегат позволяет передавать ф у н к ц и ю как параметр.
Объявление делегата имеет следующее формальное описание:
[атрибуты] [модификаторы] d e l e g a t e тип_результата имя_делегата
([список_формальных параметров]);
Модификаторами делегата могут быть:
• new
• public
• protected
• private
• internal
• unsafe (если в списке параметров используется указатель).
Тип результата должен соответствовать типу результата используе¬
мого метода.
П р и создании делегата требуется, чтобы передаваемый как делегат
метод имел ту ж е сигнатуру метода, что и в объявлении делегата.
Например:
using System;
d e l e g a t e v o i d MyDelegate();
// Этот делегат позволяет
// вызывать методы без параметров
// и без возвращаемого значения
Для вызова метода через делегата следует создать экземпляр делега¬
та, передав ему в качестве параметра метод, и м е ю щ и й ту ж е сигнатуру, что
и у делегата, а затем выполнить вызов. Для статического метода в качест
ве параметра передается имя метода, к в а л и ф и ц и р о в а н н о е именем класса.
Например:
using System;
d e l e g a t e v o i d MyDelegate();
namespace MyDelegat1
178
Лекция 18
C#. Отражения. Делегаты
{ c l a s s Class1
{[STAThread]
s t a t i c void M a i n ( s t r i n g [ ] args) {
CA var1= new CA();
// Экземпл р делегата дл нестатического метода:
MyDelegate F_d =
new
MyDelegate(var1.F_Instance);
F_d();
// Экземпл р делегата дл нестатического метода:
F_d = new MyDelegate( CA. F _ S t a t i c ) ;
F_d();
} }
p u b l i c c l a s s CA
{ p u b l i c CA()
{ }
p u b l i c v o i d F_Instance()
{ Console.WriteLine("Вызов метода класса с
использованием делегата");
public s t a t i c void F_Static()
{ Console.WriteLine("Вызов статического метода с
использованием делегата");
}
}
}
Применение делегатов как методов обратного вызова
Метод обратного вызова используется для передачи одному методу в
качестве параметра другого метода, к о т о р ы й может быть вызван через пе¬
р е д а н н ы й «указатель» на метод.
М е т о д ы обратного вызова могут п р и м е н я т ь с я в р а з л и ч н ы х целях.
Н а и б о л е е часто их используют для р е а л и з а ц и и а с и н х р о н н о й обработки
д а н н ы х или определения кода, в ы п о л н я ю щ е г о дополнительную обработ¬
ку д а н н ы х .
Например:
using System;
namespace MyDelegatе1
{
c l a s s Class1
{[STAThread]
s t a t i c void M a i n ( s t r i n g [ ] args)
CA var1= new CA();
// Создание экземпляра делегата
CA.Metod1Callback myCall =
179
{
Курс
Введение в программирование
new CA.Metod1Callback(Class1.Metod2); / / Значение
/ / параметра, передаваемое методу обратного
/ / вызова Class1.Metod2, определено
/ / в методе M e t o d l как "1".
/ / Выполнение метода обратного вызова (Metod2),
/ / переданного в качестве параметра
CA.Metod1(myCall);
}
static void Metod2 (string str2){
Console.WriteLine("Выполняется метод Metod2");
Console.WriteLine(str2);
}
}
}
using System;
namespace MyDelegatе1
{
public class C A
{ public CA() { }
public delegate void Metod1Callback(string str1);
public static void Metod1(Metod1Callback callback)
{
Console.WriteLine("Выполняется метод Metod1");
/ / Параметр callback используется для вызова
/ / метода обратного вызова и передачи ему
/ / параметра (строки "1")
callback("1");
}
}
}
В результате выполнения этого приложения
метод Metod1, а затем Metod2.
сначала будет вызван
Применение неуправляемого кода
П о у м о л ч а н и ю п р и л о ж е н и я н а C# о т н о с я т с я к у п р а в л я е м о м у к о
ду. Н о п р и н е о б х о д и м о с т и у п р а в л я е м ы й к о д может в з а и м о д е й с т в о в а т ь
с н е у п р а в л я е м ы м к о д о м . К н е у п р а в л я е м о м у коду, в ы з ы в а е м о м у из у п
р а в л я е м ы х C# п р и л о ж е н и й , м о ж н о о т н е с т и ф у н к ц и и D L L - б и б л и о т е к
и сервисы COM-компонентов. Приложение управляемого кода на
180
Лекция 18
C#. Отражения. Делегаты
я з ы к е C# т а к ж е может в к л ю ч а т ь ф р а г м е н т ы н е б е з о п а с н о г о кода. Н е б е
з о п а с н ы й к о д т о ж е о т н о с и т с я к н е у п р а в л я е м о м у коду, т а к к а к в ы д е л е
ние и освобождение памяти в нем не контролируется исполняющей
средой .NET.
Небезопасный код
Фрагмент небезопасного кода следует помечать ключевым словом
unsafe.
Например:
int i1;
unsafe { i n t *i2=&i1;}
Ключевым словом unsafe требуется обязательно помечать любой
фрагмент кода, который содержит указатель.
М о д и ф и к а т о р unsafe может быть указан для методов, свойств и к о н
структоров (за исключением статических конструкторов), а также для
блоков кода.
Например:
using System;
c l a s s Class1
{
unsafe s t a t i c v o i d M1 ( i n t * p)
// Небезопасный код: указатель на i n t
{
*p *= *p;
} // *p - доступ к значению
unsafe p u b l i c s t a t i c v o i d Main()
// Небезопасный код: применен оператор
// получения адреса (&)
{ i n t i = 4;
Console.WriteLine ( i ) ;
}
}
Ч т о б ы и с п о л ь з о в а т ь н е б е з о п а с н ы й к о д , следует у с т а н о в и т ь о п
ц и ю к о м п и л я т о р а /unsafe. Д л я этого д о с т а т о ч н о в ы б р а т ь и м я п р о е к
та в окне S o l u t i o n Explorer и через контекстное м е н ю вызвать диалог
P r o p e r t y Pages ( р и с . 1), а з а т е м н а с т р а н и ц е C o n f i g u r a t i o n P r o p e r t i e s
| B u i l d у с т а н о в и т ь з н а ч е н и е о п ц и и A l l o w u n s a f e code b l o c k s р а в н ы м
True.
181
Курс
Введение в программирование
Configuration:
[Active(Debug)
f2TJ Common Properties
73
Build
Optimize code
Debugging
Advanced
|Active(,NET)
Configuration Manager,,,
j
Conditional Lornpilation const an DEBUG; TRACE
f j j Configuration Properties
4>
Platform:
El C o d e G e n e r a t i o n
^FaTse
Check for Arithmetic Overflow/!. False
В Allow unsafe code blocks
Щ True
В Errors and W a r n i n g s
•
Warning Level
Warning level 4
Treat Warnings As Errors
False
Out
Щ Output Path
XML Documentation File
bin\Debug\
Generate Debugging Informatioi True
Register for COM interop
False
Allow unsafe code blocks
Enable use of the unsafe keyword (/unsafe).
Рис. 1. Диалог Property Pages
Указатели м о ж н о использовать только с размерными типами, масси
вами и строками. П р и задании указателя на массив первый элемент мас¬
сива должен быть размерного типа.
В ы п о л н я ю щ а я среда . N E T для эффективного управления памятью
при удалении одних объектов «перемещает» другие объекты, чтобы и с
ключить фрагментацию памяти свободными блоками памяти. Таким об
разом, в ы п о л н я ю щ а я среда . N E T по умолчанию не гарантирует, что объ¬
ект, на который получен указатель, всегда будет иметь один и тот ж е ад¬
рес. Для предотвращения перемещения объекта следует использовать
оператор f i x e d , который имеет следующее формальное описание:
f i x e d ( тип* имя_указателя = выражение )
выполн емый_оператор_или_блок
В качестве типа м о ж н о указывать любой неуправляемый тип или
void. Выражение является указателем на заданный тип. Ф и к с а ц и я объек
та применяется только для указанного выполняемого оператора или бло¬
ка. Доступ к ф и к с и р о в а н н о й переменной не ограничен областью видимо¬
сти небезопасного кода. Поэтому ф и к с и р о в а н н а я переменная может ука
зывать на значение, располагаемое в более ш и р о к о й области видимости,
чем данная область видимости небезопасного кода. П р и этом компилятор
C# не выдает предупреждений о такой ситуации.
Однако компилятор C# не позволит установить указатель на управ
ляемую переменную вне оператора f i x e d .
182
Лекция 18
C#. Отражения. Делегаты
Например:
class
Point
{ p u b l i c i n t x, y; }
c l a s s Class1
{[STAThread]
s t a t i c void Main(str ing[]
args)
{
unsafe
{
Point pt = new P o i n t ( ) ;
// pt — это управляемая
// переменная
fixed ( i n t * p = &pt.x ) {
*p = 1 }
// pt.x -
// указывает на значение
// размерного типа
}
} }
Одним оператором f i x e d м о ж н о фиксировать несколько указателей,
но только в том случае, если о н и одного типа.
Например:
f i x e d (byte* pa1 = array1,
pa2 = a r r a y 2 )
{... }
В том случае, если требуется зафиксировать указатели различных ти¬
пов, м о ж н о использовать вложенные операторы f i x e d .
Например:
f i x e d ( i n t * p1 = &p.x)
f i x e d (double* p2 = &array1[5])
{
}
Указатели, которые и н и ц и а л и з и р о в а н ы оператором f i x e d , н е могут
быть изменены.
Если объект, на который устанавливается указатель, размещается в
стеке (например, переменная типа i n t ) , то его местоположение ф и к с и р о
вать н е требуется. Разместить блок памяти в стеке м о ж н о и я в н ы м обра
зом, используя оператор stackalloc, который имеет следующее формаль¬
н о е описание:
тип * им _указател
= s t a c k a l l o c тип [ выражение
];
В качестве типа может быть указан любой неуправляемый тип.
183
Курс
Введение в программирование
Например:
using System;
c l a s s Class1
{ p u b l i c s t a t i c unsafe v o i d
Main()
{
i n t * a1 = s t a c k a l l o c i n t [ 1 0 0 ] ;
i n t * p = a1;
// Указатель на первый
// элемент массива
*p++ = *p++ = 1;
f o r ( i n t i=2; i<100;
++p)
*p = p[-1] + p[-2];
f o r ( i n t i=0; i<10; ++i) Console.Wr i t e L i n e (a1[ i ] ) ;
}
}
Время ж и з н и указателя, инициализированного с применением
s t a c k a l l o c , ограничено временем в ы п о л н е н и я метода, в котором этот
указатель объявлен. И н и ц и а л и з и р о в а т ь указатели посредством s t a c k a l l o c
м о ж н о только д л я локальных переменных.
DLL-библиотеки
Д л я того чтобы вызвать метод и з D L L - б и б л и о т е к и , его следует объ
я в и т ь с м о д и ф и к а т о р о м extern и атрибутом DllImport.
Например:
[DllImpo rt("Имя_библиотеки.dll")]
s t a t i c extern i n t M1(int i 1 , s t r i n g s 1 ) ;
Класс атрибута D l l I m p o r t A t t r i b u t e имеет следующее определение:
namespace
System.Runtime.InteropServices
{
[AttributeUsage(AttributeTargets.Method)]
public class DllImportAttribute: System.Attribute
{
p u b l i c D l l I m p o r t A t t r i b u t e ( s t r i n g dllName) {...}
public CallingConvention
CallingConvention;
p u b l i c CharSet CharSet;
// Набор символов
p u b l i c s t r ing E n t r y P o i n t ;
// Им метода
p u b l i c bool E x a c t S p e l l i n g ;
// Точное
// соответствие написани имени метода
p u b l i c bool PreserveSig;
// Определяет, будет ли
184
Лекция 18
C#. Отражения. Делегаты
// предотвращено изменение сигнатуры метода (по умолчанию
// установлено значение t r u e ) .
// При изменении сигнатуры возвращаемое значение будет
// иметь тип HRESULT и будет добавлен out-параметр r e t v a l
p u b l i c bool S e t L a s t E r r o r ;
p u b l i c s t r i n g Value { get {...} }
}
}
Атрибут DllImport имеет один п о з и ц и о н н ы й параметр, определяю
щ и й имя DLL-библиотеки, и пять именованных параметров. Параметр
EntryPoint позволяет указать и м я метода из DLL-библиотеки. П р и этом
и м я метода, помечаемого д а н н ы м атрибутом, может отличаться от и м е н и
метода в DLL-библиотеке.
Например:
[DllImport("myDll.dll",
EntryPoint="M1")]
s t a t i c extern i n t New_name_of_M1(int i 1 , s t r i n g s1);
И м е н о в а н н ы й параметр CharSet определяет используемый в D L L библиотеке набор символов ( A N S I или Unicode). П о умолчанию исполь
зуется значение CharSet.Auto.
Например:
[ D l l I m p o r t ( " m y D l l . d l l " , CharSet C h a r S e t . A n s i ) ]
s t a t i c extern i n t M1( i n t i 1 , s t r ing s1);
Для каждого типа параметра при вызове метода из DLL-библиотеки
в ы п о л н я ю щ а я среда . N E T производит подразумеваемое по умолчанию
преобразование т и п о в ( н а п р и м е р , тип s t r i n g в тип LPSTR (Win32). Для т о
го чтобы я в н ы м образом указать тип, используемый в методе D L L - б и б л и
отеки, следует применить к параметру атрибут MarshalAsAttribute.
Например:
[ D l l I m p o r t ( " m y D l l . d l l " , CharSet CharSet.Unicode)]
s t a t i c extern i n t M1( i n t i 1 ,
[MarshalAs(UnmanagedType.LPWStr)]
s t r i n g s1);
Атрибут MarshalAsAttr ibute может быть прикреплен к полю, методу
или параметру. П р и к р е п л е н и е данного атрибута к методу позволяет ука
зать я в н о е преобразование типа для возвращаемого значения.
185
Курс
Введение в программирование
Глава 5. Системы проектирования
Л е к ц и я 1 9 . Б и б л и о т е к а к л а с с о в MFC с р е д ы п р о е к
т и р о в а н и я Visual S t u d i o .NET. Д и а л о г и
С о з д а н и е п р и л о ж е н и й на С + + в Visual Studio .NET
Среда Visual Studio . N E T позволяет создавать приложения с исполь
зованием различных библиотек:
• библиотеки M F C для С + + , предоставляющей ш и р о к и й набор клас
сов для создания S D I - и M D I - п р и л о ж е н и й , а также приложений, ре
ализующих работу с базами данных, и серверных W E B - п р и л о ж е н и й ;
• библиотеки активных шаблонов A T L ;
• библиотеки . N E T Framework, используемой при разработке п р и л о
ж е н и й управляемого кода. Эта библиотека может применяться как
для приложений управляемого кода на С + + , так и для создания п р и
ложения на языках C# и Visual Basic.
MFC-приложения
M F C - п р и л о ж е н и я м о ж н о реализовывать как:
• однодокументные приложения (Single document);
• многодокументные приложения (Multiple documents);
• приложения-диалоги (Dialog based).
Тип создаваемого приложения выбирается на странице Application
type мастера создания M F C - п р и л о ж е н и я (рис. 1).
Черты пользовательского интерфейса для создаваемого диалога в ы
бираются на страницах User Interface Features (рис.2) и Advanced Features
(рис. 3) мастера создания M F C - п р и л о ж е н и я .
Приложения-диалоги
Базовым классом любого Winsows-приложения, основанного на
о к о н н о м интерфейсе, является класс cWinApp.
П р и создании приложения-диалога мастер построения M F C - п р и л о
ж е н и я добавляет в проект два класса:
• класс приложения, производный от cWinApp;
• класс диалога, производный от CDialog.
Класс приложения имеет следующее объявление и реализацию:
186
Лекция 19
Библиотека классов MFC среды проектирования Visual Studio .NET. Диалоги
Рис. 1. Страница Application Type мастера создания M F C приложения
Рис. 2. Страница User Interface Features мастера создания M F C приложения
187
Курс
Введение в программирование
MFC Application Wizard
D1
Рис. 3. Страница Advanced Features мастера создания M F C приложения
// Заголовочный файл
c l a s s CDIApp : p u b l i c CWinApp
{public:
CD1App();
public:
v i r t u a l BOOL I n i t I n s t a n c e ( ) ;
// Первый
// выполняемый метод
// Implementation
DECLARE_MESSAGE_MAP()
};
extern CDIApp theApp;
// Переменная - приложение
// Файл реализации Dl.cpp
#include " s t d a f x . h "
#include "D1.h"
#include "DIDlg.h"
// CD1App
BEGIN_MESSAGE_MAP(CD1App, CWinApp)
// Обрабатываемые события
ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()
CDIApp::CD1App(){ }
//
Конструктор
188
Лекция 19
Библиотека классов MFC среды проектирования Visual Studio .NET. Диалоги
CD1App theApp;
BOOL CD1App::InitInstance()
{ CWinApp::InitInstance();
AfxEnableControlContainer();
S e t R e g i s t r y K e y ( _ T ( " L o c a l AppWizard-Generated
Applications"));
CD1Dlg d l g ;
// Создание объекта диалога
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal(); // Отображение
// диалога
i f (nResponse == IDOK) { }
e l s e i f (nResponse == IDCANCEL) { }
return FALSE;
// Завершение приложения
}
Класс диалога имеет следующее объявление и реализацию:
// Заголовочный файл
c l a s s CD1Dlg : p u b l i c CDialog
{public:
CD1Dlg(CWnd* pParent = NULL); // Конструктор
enum { IDD = IDD_D1_DIALOG };
// Ресурс диалога
protected:
// Поддержка DDX/DDV:
v i r t u a l v o i d DoDataExchange(CDataExchange* pDX);
// Реализация
protected:
HICON m_hIcon;
// Функции таблицы обрабатываемых событий
v i r t u a l BOOL O n I n i t D i a l o g ( ) ;
afx_msg v o i d OnSysCommand(UINT nID, LPARAM lParam);
afx_msg v o i d OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
};
// Файл реализации D1Dlg.cpp
#include " s t d a f x . h "
#include "D1.h"
#include "D1Dlg.h"
c l a s s CAboutDlg : p u b l i c CDialog
// Класс
// вспомогательного диалога
189
Курс
Введение в программирование
{ p u b l i c : CAboutDlg();
enum { IDD = IDD_ABOUTBOX }; // Ресурс диалога
protected:
v i r t u a l v o i d DoDataExchange(CDataExchange* pDX);
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { }
v o i d CAboutDlg::DoDataExchange(CDataExchange* pDX)
{ CDialog::DoDataExchange(pDX);}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// Класс окна диалога приложения
CD1Dlg::CD1Dlg(CWnd* pParent /*=NULL*/)
: CDialog(CD1Dlg::IDD, pParent)
{ m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); }
v o i d CD1Dlg::DoDataExchange(CDataExchange* pDX)
{ CDialog::DoDataExchange(pDX); }
BEGIN_MESSAGE_MAP(CD1Dlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
END_MESSAGE_MAP()
// Методы обработки событий
BOOL CD1Dlg::OnInitDialog()
{ CDialog::OnInitDialog();
ASSERT((IDM_ABOUTBOX & OxFFFO) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < OxFOOO);
CMenu* pSysMenu = GetSystemMenu(FALSE); // Указатель
// на системное меню
i f (pSysMenu != NULL)
// Добавление пунктов к
{ CStr ing strAboutMenu;
//системному меню
strAboutMenu.LoadString(IDS_ABOUTBOX);
i f (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING,
IDM_ABOUTBOX, strAboutMenu);
}
}
SetIcon(m_hIcon, TRUE);
// Определение крупной
// пиктограммы
SetIcon(m_hIcon, FALSE); // Определение мелкой пиктограммы
190
Лекция 19
Библиотека классов MFC среды проектирования Visual Studio .NET. Диалоги
return TRUE;
}
v o i d CD1Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{ i f ((nID & OxFFFO) == IDM_ABOUTBOX)
{ CAboutDlg dlgAbout; dlgAbout.DoModal(); }
e l s e { CDialog::OnSysCommand(nID, lParam); }
}
v o i d CD1Dlg::OnPaint() { CDialog::OnPaint(); }
HCURSOR CD1Dlg::OnQueryDragIcon()
// Запрос курсора
{ return static_cast<HCURSOR>(m_hIcon); }
Для отображения окна диалога следует:
• создать ресурс диалога, и м е ю щ и й конкретный вид диалогового ок¬
на, и разместить в нем требуемые элементы управления (каждый
элемент управления также определяется своим идентификатором
ресурса);
• создать класс, наследуемый от класса CDialog (или производного от
него), и связать создаваемый класс с ресурсом диалога.
Связывание командных к н о п о к с методами — обработчиками собы
тий и идентификаторов ресурсов элементов управления с переменными
выполняется в редакторе ресурсов.
Для назначения к н о п к е метода обработчика события м о ж н о выпол
нить на ней двойной щелчок м ы ш ь ю (для события BN CLICKED) или выде
лить элемент управления и выполнить команду контекстного меню A d d
Event Handler.
П о умолчанию для командной к н о п к и , в ы п о л н я ю щ е й завершение
диалога, будет вставлен следующий метод — обработчик события:
v o i d CD1Dlg::OnBnClickedOk() {
OnOK(); // OnOK - метод базового класса CDialog
}
И м я метода — обработчика события формируется из префикса On,
и м е н и события и идентификатора элемента управления.
Обработчик события добавляется как новый член класса диалога.
П р и добавлении каждого нового метода обработчика события в таб
лицу сообщений также добавляется н о в ы й вход.
Таблица сообщений (иногда называемая также таблицей событий)
указывается между макросами BEGIN MESSAGE MAP и END MESSAGE MAP. М а к
рос BEGINMESSAGE MAP имеет два параметра — имя класса, обрабатывающе
го д а н н ы е сообщения, и имя базового класса. Чтобы определить, что д а н 191
Курс
Введение в программирование
н ы й класс имеет таблицу сообщений, в заголовочном файле указывается
макрос DECLAREMESSAG E_MAP.
Например:
BEGIN_MESSAGE_MAP(CD1Dlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDOK, &CD1Dlg::OnBnClickedOk)
END_MESSAGE_MAP()
Каждый вход таблицы сообщений содержит и м я события (напри
мер, ON_BN_CLICKED), идентификатор ресурса элемента управления (напри
мер, IDOK) и и м я метода — о б р а б о т ч и к а с о б ы т и я ( н а п р и м е р ,
&CD1Dlg::OnBnClickedOk).
Диалог может быть создан как:
• модальный диалог, завершение которого необходимо выполнить до
продолжения работы с приложением (диалог отображается вызовом
метода DoModal);
• немодальный диалог, позволяющий получать одновременный д о
ступ к другим немодальным диалогам данного приложения (диалог
создается вызовом метода Create и сразу отображается, если установ
лен стиль диалога WS_VISIBLE).
Для того чтобы отобразить созданный диалог к а к модальный, следу
ет создать объект диалога и выполнить для него метод DoModal().
Например:
CD1Dlg d l g ;
INTPTR nResponse = dlg.DoModal();
Если предполагается определить диалог к а к главное о к н о приложе
н и я , то необходимо для объекта приложения установить значение свойст
ва m_pMainWnd (CWnd* m_pMainWnd;).
Например:
CD1Dlg d l g ;
m_pMainWnd = &dlg;
// AfxGetApp()->m_pMainWnd
// AfxGetApp() возвращает для
// приложени указатель на
// объект типа CWinApp
INT_PTR nResponse = dlg.DoModal();
192
Лекция 19
Библиотека классов MFC среды проектирования Visual Studio .NET. Диалоги
Для модального диалога следует проверять код завершения диалога.
Например:
INT_PTR nResponse = dlg.DoModal();
if
(nResponse == IDOK)
{ }
e l s e i f (nResponse == IDCANCEL) { }
Для того чтобы отобразить диалог к а к немодальный, следует создать
объект диалога и выполнить для него метод C reate ( ) .
Например:
CMyDialog* pDialog;
// Указатель на объект диалога
v o i d CMyWnd::OnSomeAction()
{
// pDialog может быть инициализирован как NULL
// в конструкторе или классе CMyWnd
pDialog = new CMyDialog();
if(pDialog
!= NULL)
{
BOOL r e t =
pDialog->Create(IDD_MYDIALOG,this); // Параметр
// указывает используемый ресурс диалога
i f ( ! r e t ) AfxMessageBox(" Ошибка при создании диалога");
pDialog->ShowWindow(SW_SHOW);
}
e l s e AfxMessageBox(" Ошибка с объектом диалога");
}
К л а с с ы д и а л о г о в б и б л и о т е к и MFC
Библиотека M F C содержит большой набор классов, предназначен
ных для создания диалоговых окон. Н а следующей схеме приведена и е
рархия классов диалогов, наследуемых от класса CDialog.
Класс CDialog
Класс CDialog является базовым классом, используемым для отобра
ж е н и я на экране диалоговых окон, называемых также диалогами.
Есть два типа диалоговых окон — модальные и немодальные.
Как уже отмечалось, для реализации диалога следует создать в редак
торе диалога шаблон диалогового окна, а затем с помощью ClassWizard (или
вручную) создать производный класс от CDialog и определить в нем необ193
Курс
Введение в программирование
-
CDialog]]
[CCommonDialogl
[CColorPialocTl
1CFileDialog
I
[ CFindReplacePialogl
[CFontDialog
I
[COlePialog
I
[COleBusyPialogl
1 COleChangelconPialog 1
1 COleChangeSourcePialogl
[ COleConvertPialogl
iCOlelnsertPialog 1
[COleLinksPialog
1
LfCOleUpdatePialog 1
1 COlePasteSpecialPialogl
'
[ COlePropertiesPialog
1
[ CPageSetupPialog1
[CPrintPialogl
I
[CPrintPialogExl
[COlePropertyPagel
[ CPropertyPage
1
user d i a l o g boxes
[CPHtmlPialogl
I
1 CMultiPagePHtmlPialog1
ходимые методы — обработчики сообщений для расположенных в исполь
зуемом шаблоне диалога элементов управления. ClassWizard автоматически
будет добавлять список обрабатываемых сообщений в таблицу сообщений
производного класса, а в заголовочном файле будет указан м а к р о с
DECLARE_MESSAGE_MAP ( ) , который указывает, что класс содержит таблицу со¬
общений.
Д л я создания диалоговых о к о н на основе существующего ресурса
диалога м о ж н о использовать:
• метод DoModal (для модального диалога);
• метод Create (для немодального диалога);
Е с л и ш а б л о н д и а л о г а отсутствует, то м о ж н о с о з д а т ь ш а б л о н д и а
л о г а , и с п о л ь з у я структуру DLGTEMPLATE, а з а т е м , п о с л е с о з д а н и я о б ъ е к
та д и а л о г а , в ы з в а т ь м е т о д ы C r e a t e I n d i r e c t и л и I n i t M o d a l I n d i r e c t и
DoModal.
194
Лекция 19
Библиотека классов MFC среды проектирования Visual Studio .NET. Диалоги
Модальное диалоговое о к н о автоматически закрывается при щелчке
пользователя на кнопках типа O K и л и Cancel и л и п р и вызове метода
EndDialog. Отметим, что метод EndDialog только скрывает о к н о диалога, а
для его удаления следует использовать ф у н к ц и ю DestroyWindow.
Для обмена значениями с элементом управления используется метод
CWnd: : UpdateData. Этот метод автоматически вызывается и п р и щелчке
пользователя на к н о п к е типа O K , и при и н и ц и а л и з а ц и и элементов управ
л е н и я методом OnInitDialog.
Метод OnInitDialog вызывается после создания всех элементов у п
равления диалогового окна, н о перед их отображением.
Д л я о п р е д е л е н и я ф о н а д и а л о г о в ы х о к о н используется метод
CWinApp::SetDialogBkColor.
Последовательность создания диалогового окна включает следую¬
щ и е шаги:
1.
проектирование в редакторе диалога шаблона диалогового окна с
включением в него всех требуемых элементов управления и наст¬
р о й к и их свойств;
2.
создание класса, производного от CDialog, с описанием в нем пере¬
менных и обработчиков событий, а также указанием используемого
шаблона диалога;
3.
определение для каждого элемента управления переменной или объек
та, используемых для доступа к значению данного элемента управления;
4.
определение необходимых методов обработчиков событий для каж
дого элемента управления;
5.
с о з д а н и е объекта разработанного производного класса диалога
(фактически вызов конструктора) и создание диалогового окна:
Для модального диалога
Для немодального диалога
вызов конструктора с параметром, вызов конструктора без параметра
указывающим I D
шаблона диалога
вызов метода D o M o d a l
6.
вызов метода Create с параметром,
указывающим ID шаблона диалога
переопределение метода OnInitDialog и включение в него вызова ме¬
тода базового класса и необходимых действий по и н и ц и а л и з а ц и и
диалогового окна.
Класс CDialog предоставляет следующие конструкторы объекта:
CDialog (LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL);
CDialog (UINT nIDTemplate, CWnd* pParentWnd = NULL);
CDialog ( ) ;
195
Курс
Введение в программирование
Параметр lpszTemplateName — это строка, содержащая и м я ресурса
шаблона диалога, nIDTemplate — значение I D ресурса шаблона диалога.
П о умолчанию редактор ресурсов присваивает шаблонам диалога иденти¬
ф и к а т о р ы , начинающиеся с префикса I D D _ . Параметр pParentWnd задает
указатель на родительское о к н о и л и окно собственник (типа CWnd), кото¬
рому принадлежит этот диалог. Значение N U L L показывает, что роди
тельским о к н о м является главное о к н о приложения.
Конструктор без параметров используется для создания модального
окна диалога на основе шаблона, расположенного в памяти. П р и этом
применяется метод I n i t M o d a l I n d i r e c t . Д л я создания модального диалога
после вызова конструктора следует вызвать метод DoModal.
Класс CDialog предоставляет следующие методы Create для создания
немодального диалога:
BOOL Create (LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL);
BOOL Create (UINT nIDTemplate, CWnd* pParentWnd = NULL);
П р и успешном завершении создания диалогового окна и инициали¬
зации эти методы возвращают ненулевое значение.
Если в шаблоне диалога н е установлен стиль W S V I S I B L E , то д л я
отображения диалога необходимо вызвать метод ShowWindow.
Класс CDialog предоставляет большой набор методов, предназна
ч е н н ы х для работы с диалоговым о к н о м , включая следующие:
• DoModal — используется для создания модального диалогового окна.
• NextDlgCt r l — перемещает фокус на следующий элемент управления
диалогового окна (а с последнего элемента управления — на пер¬
вый).
• P r e v D l g C t r l — перемещает фокус на предыдущий элемент управле
н и я диалогового окна (а с первого элемента управления — на по¬
следний);
• GotoDlgCtrl (CWnd* pWndCtrl) — перемещает фокус на указываемый
параметром pWndCtrl элемент управления (чтобы получить значение
параметра pWndCtrl, м о ж н о вызвать метод CWnd : : GetDlgItem).
• SetDefID (UINT nID) — изменяет командную кнопку, используемую
по умолчанию (параметр задает I D командной к н о п к и ) .
• SetHelpID (UINT nIDR) — определяет контекстно-зависимый иденти
фикатор справки (ID) для диалогового окна.
• EndDialog — используется для закрытия модального диалогового окна.
• O n I n i t D i a l o g — вызывается д л я обработки с о о б щ е н и я WM INITDIALOG, к о т о р о е и н и ц и и р у е т с я п р и в ы п о л н е н и и м е т о д о в C r e a t e ,
C r e a t e I n d i r e c t и л и DoModal. П р и п е р е о п р е д е л е н и и этого метода
п е р в о н а ч а л ь н о д о л ж е н быть в ы з в а н метод OnInitDialog базового
196
Лекция 19
Библиотека классов MFC среды проектирования Visual Studio .NET. Диалоги
класса. П р и у с п е ш н о м з а в е р ш е н и и метод возвращает з н а ч е н и е
TRUE.
• OnSetFont (CFont* pFont) — определяет шрифт, используемый п о
умолчанию для всех элементов управления диалогового окна.
• OnOK — обработчик сообщения, вызываемый при щелчке пользовате
ля на командной к н о п к е O K (с идентификатором I D O K ) .
• OnCancel — обработчик сообщения, вызываемый при щелчке пользова
теля на командной кнопке Cancel (с идентификатором I D C A N C E L ) .
Стандартные диалоги
Класс CCommonDialog — это базовый класс, инкапсулирующий поведе
ние стандартных диалогов Windows. Библиотека M F C содержит классы
стандартных диалогов, производных от CCommonDialog, включая следующие:
•
•
•
•
•
•
•
•
CFileDialog
CFontDialog
CColorDialog
CPageSetupDialog
CPrintDialog
CPrintDialogEx
CFindReplaceDialog
COleDialog
Для использования класса CCommonDialog следует подключить заголо¬
вочный файл afxdlgs.h.
Класс CFileDialog
Класс C F i l e D i a l o g инкапсулирует поведение диалогов Open и Save As.
Для работы с объектом типа C F i l e D i a l o g сначала следует создать
этот объект, используя конструктор, а затем управлять д а н н ы м к о м п о н е н
том через поля структуры m_ofn типа O P E N F I L E N A M E .
Структура OPENFILENAME содержит и н ф о р м а ц и ю , используемую
ф у н к ц и я м и GetOpenFileName и GetSaveFileName для и н и ц и а л и з а ц и и диало¬
гов Open или Save As.
Структура OPENFILENAME имеет следующее определение:
typedef s t r u c t tagOFN {
DWORD l S t r u c t S i z e ;
HWND hwndOwner;
HINSTANCE hInstance;
LPCTSTR l p s t r F i l t e r ;
// Длина структуры в байтах
// Дескриптор окна владельца
// данного диалога или NULL
// Указатель на буфер, содержащий
197
Курс
Введение в программирование
// пары null-ограниченных строк:
// первая строка - это описание
// фильтра (например: "Программы"),
// вторая строка - шаблон
// ( например: "*.exe;*.com")"
LPTSTR l p s t r C u s t o m F i l t e r ;
DWORD
nMaxCustFilter;
DWORD n F i l t e r I n d e x ;
LPTSTR l p s t r F i l e ;
// Указатель на буфер,
// который содержит
// им файла, используемое дл
// инициализации пол F i l e Name,
// или NULL. При успешном завершении
// функции GetOpenFileName или
//GetSaveFileName поле содержит
// логический диск, путь и им
// выбранного файла.
DWORD
nMaxFile;
LPTSTR l p s t r F i l e T i t l e ; // Указатель на буфер,
// содержащий им и расширение выбранного файла
DWORD
nMaxFileTitle;
LPCTSTR l p s t r I n i t i a l D i r ; // Указатель на n u l l // ограниченную строку, которая представляет каталог,
// используемый дл инициализации диалога
LPCTSTR
lpstrTitle;
DWORD
Flags;
WORD
nFileOffset;
WORD
nFileExtension;
LPCTSTR
lpstrDefExt;
LPARAM
lCustData;
LPOFNHOOKPROC lpfnHook;
LPCTSTR
lpTemplateName;
f (_WIN32_WINNT >= 0x0500)
void *
pvReserved;
DWORD
dwReserved;
DWORD
FlagsEx;
#endif // (_WIN32_WINNT >= 0x0500)
} OPENFILENAME, *LPOPENFILENAME;
Если метод DoModal, используемый для отображения диалога типа
C F i l e D i a l o g , возвращает з н а ч е н и е IDOK, т о для получения и н ф о р м а ц и и о б
и м е н и файла м о ж н о использовать методы члены класса C F i l e D i a l o g .
198
Лекция 19
Библиотека классов MFC среды проектирования Visual Studio .NET. Диалоги
Если предполагается разрешить пользователю о д н о в р е м е н н о вы¬
брать более одного файла, т о д о вызова метода D o M o d a l следует устано¬
вить флаг O F N _ A L L O W M U L T I S E L E C T .
Например:
OPENFILENAME ofn;
// Данные дл диалога
char s z F i l e [ 2 6 0 ] ;
// Буфер для имени файла
HWND hwnd;
// Окно — владелец отображаемого диалога
HANDLE hf;
// Дексриптор файла
// Инициализация структуры OPENFILENAME
ZeroMemory(&ofn, sizeof(OPENFILENAME)); // Макрос,
// заполн ющий нул ми указанный блок пам ти
o f n . l S t r u c t S i z e = sizeof(OPENFILENAME);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = szFile;
ofn.nMaxFile = s i z e o f ( s z F i l e ) ;
o f n . l p s t r F i l t e r = "Все\0*.*\0Текстовые\0*.TXT\0";
o f n . n F i l t e r I n d e x = 1;
o f n . l p s t r F i l e T i t l e = NULL;
o f n . n M a x F i l e T i t l e = 0;
o f n . l p s t r I n i t i a l D i r = NULL;
o f n . F l a g s = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
// Отображение диалога Open
i f (GetOpenFileName(&ofn)==TRUE)
hf = C r e a t e F i l e ( o f n . l p s t r F i l e , GENERIC_READ,
0, (LPSECURITY_ATTRIBUTES) NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
Класс C F i l e D i a l o g содержит п о л е m_ofn, которое является структурой
т и п а O P E N F I L E N A M E , используемой д л я и н и ц и а л и з а ц и и д и а л о г о в
Open и Save As.
Д л я создания д а н н о г о диалога п р и м е н я е т с я следующий конструк¬
тор:
C F i l e D i a l o g ( BOOL bOpenFileDialog,
LPCTSTR l p s z D e f E x t = NULL,
LPCTSTR lpszFileName = NULL,
DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
LPCTSTR l p s z F i l t e r = NULL,
CWnd* pParentWnd = NULL,
DWORD dwSize = s i z e o f ( OPENFILENAME ) ) ;
199
Курс
Введение в программирование
Параметр bOpenFileDialog определяет типа создаваемого диалога:
значение T R U E указывает диалог Open, а F A L S E — диалог Save As. Пара¬
метр lpszDefExt указывает используемое по умолчанию р а с ш и р е н и е
файла. Если пользователь не вводит р а с ш и р е н и е файла в поле File name,
то д а н н о е значение автоматически добавляется к и м е н и файла. Если зна
ч е н и е этого параметра равно N U L L , то р а с ш и р е н и е не добавляется. П а
раметр lpszFileName — это N U L L или и м я файла, отображаемое при от
крытии данного диалога. Параметр dwFlag s определяет ф л а ж к и , использу
емые для настройки диалога; l p s z F i l t e r — это пары строк, определяющие
фильтры для выбора файлов. П р и использовании структуры типа O P E N F I L E N A M E строки фильтра следует ограничивать символом '\0', а в д а н
ном параметре следует использовать символ |. Параметр pParentWnd — это
указатель на о к н о владелец или родительское о к н о данного диалога. Раз
мер структуры O P E N F I L E N A M E указывается параметром dwSize.
Например:
v o i d CMyDlg::OnFileOpen()
{
// s z F i l t e r s - строка с описанием и шаблоном фильтров
char C M y D l g : : s z F i l t e r s [ ] =
" Текстовые файлы (*.txt)|*.my| Все файлы(*.*)|*.*||";
// Создание диалога Open, использующего
// дл отображаемых файлов расширение t x t
C F i l e D i a l o g f i l e D l g = new C F i l e D i a l o g (TRUE,
"txt",
"*.txt",
OFN_FILEMUSTEXIST| OFN_HIDEREADONLY,
szFilters,
this);
i f ( f i l e D l g . D o M o d a l ()==IDOK ) // Отображение диалога
{
CStr ing pathName = fileDlg.GetPathName();
CStr ing fileName = f i l e D l g . G e t F i l e T i t l e ( ) ;
}
Отображение диалога стандартного Open также м о ж н о выполнить
вызовом метода GetOpenFileName.
Например:
i f (GetOpenFileName(&ofn)==TRUE)
hf = C r e a t e F i l e ( o f n . l p s t r F i l e ,
200
GENERIC_READ,
Лекция 19
Библиотека классов MFC среды проектирования Visual Studio .NET. Диалоги
0, (LPSECURITYATTRIBUTES) NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
Класс CColorDialog
Класс CColorDialog предназначается д л я р е а л и з а ц и и стандартного
диалога Color, используемого д л я выбора цвета. Структура CHOOSECOLOR
п р и м е н я е т с я д л я и н и ц и а л и з а ц и и диалога. Д л я отображения стандартно
го диалога Color вызывается метод ChooseColor.
Например:
CHOOSECOLOR cc;
// Структура дл инициализации диалога
s t a t i c COLORREF a c r C u s t C l r [ 1 6 ] ; // Массив цветов
HWND hwnd;
// Окно владелец
HBRUSH hbrush;
// Указатель кисти
s t a t i c DWORD rgbCurrent;
// Первоначально выбранный цвет
ZeroMemory(&cc, s i z e o f ( c c ) ) ;
cc.lStructSize = sizeof(cc);
cc.hwndOwner = hwnd;
c c . l p C u s t C o l o r s = (LPDWORD) a c r C u s t C l r ;
c c . r g b R e s u l t = rgbCurrent;
c c . F l a g s = CC_FULLOPEN | CC_RGBINIT;
if
(ChooseColor(&cc)==TRUE) {
hbrush = C r e a t e S o l i d B r u s h ( c c . r g b R e s u l t ) ;
rgbCurrent = c c . r g b R e s u l t ;
}
201
Курс
Введение в программирование
Л е к ц и я 2 0 . Б и б л и о т е к а к л а с с о в MFC с р е д ы п р о е к
т и р о в а н и я Visual S t u d i o .NET.
SDI и MDI п р и л о ж е н и я
Архитектура «документ-отображение»
Для реализации S D I и M D I - п р и л о ж е н и й посредством библиотеки
классов M F C применяется механизм «документ/отображение». Это поз
воляет отображать один документ различными способами.
Документы и отображения
Архитектура «документ/отображение» (document/view) базируется
на взаимодействии четырех основных классов.
• Класс CDocument (или COleDocument) реализует основные возможности
внутреннего представления документа. Этот класс используется д л я
управления д а н н ы м и (обычно документ представляет модуль д а н
ных, открываемых по команде Open и сохраняемых командой Save
меню File).
• Класс CView (или один и з его наследуемых классов) отвечает за отоб
ражение содержания документа и л и любой графической и н ф о р м а
ции. Объекты этого класса будем называть отображениями. Одному
документу может быть сопоставлено несколько различных объектов
отображений. П р и этом отображение пристыковывается или сопос
тавляется документу.
Отображение представляет вид документа на экране и является н е
которой средой, взаимосвязывающей документ и пользователя. Объект
«отображение» воспроизводит вид документа на экране и интерпретирует
действия пользователя как операции над документом. Класс отображения
также форматирует изображение к а к для печати, так и для предваритель¬
ного просмотра.
• К л а с с CFrameWnd ( и л и другой к л а с с W i n d o w s - о к н а , в к л ю ч а я
CMDIFrameWnd и CMDIChildWnd) представляют объекты, обеспечиваю
щ и е окно-рамку (frame) вокруг одного или нескольких отображе¬
н и й документа.
• Класс CDocTemplate (или классы CSingleDocTemplate, CMultiDocTemplate)
поддерживают объект шаблона документа, координирующий
один или несколько существующих документов заданного типа, и
управляют созданием документа, отображения и окна-рамки для
этого типа.
202
Лекция 20
Библиотека классов MFC среды проектирования
Visual Studio .NET. SDI и MDI приложения
Отображение
Рис. 1. Взаимосвязь объектов «документ — отображение — окно-рамка»
Объект «отображение» привязан к объекту «окно-рамка». Н а следу
ю щ е м рисунке изображена взаимосвязь объектов «документ->отображение->окно-рамка».
Объект «отображение» используется не только для представления
документов на экране. О н же представляет документ и для печати, и для
предварительного просмотра печатаемого документа.
С п о м о щ ь ю механизма «документ-отображение» реализуется разде
ление данных, их экранное представление и обработка действий пользо
вателя.
Операции по и з м е н е н и ю данных реализуются классами документа.
Объект отображение только вызывает этот интерфейс для доступа и об
новления данных.
Документы, сопоставленные и м отображения, о к н а - р а м к и создают
ся с использованием шаблона документа. К а ж д ы й шаблон документа и с
пользуется для создания всех документов одного типа и управления ими.
Создание нового документа и сопоставленного ему отображения и
окна-рамки. выполняется р а з л и ч н ы м и объектами: объектом «приложе¬
ние», шаблоном документа, созданным документом и созданным о к н о м рамкой.
Следующая таблица иллюстрирует, к а к и м и объектами создаются
шаблон документа, документ, о к н о - рамка и отображение.
203
Курс
Введение в программирование
Создающий объект
Создаваемый объект
П р и л о ж е н и е (Application object)
Ш а б л о н документа
Ш а б л о н документа (Document template)
Документ
Ш а б л о н документа (Document template)
Окно-рамка
О к н о - р а м к а (Frame window)
Отображение (View)
Все о к о н н ы е M F C - п р и л о ж е н и я имеют к а к м и н и м у м два объекта:
объект «приложение», производный от класса CWinApp, и объект «главное
окно», производный от класса CWnd или его потомков — классов CFrameWnd,
CMDIFrameWnd и CDialog.
Объект «документ» отвечает за внутреннее представление данных,
показываемых объектом «отображене». Объект «отображение» предназ¬
начен для манипулирования д а н н ы м и объекта документа. Объект «отоб
ражение» состыковывается с объектом «документ» и о к н о м - р а м к о й , о б
разуя цепочку «документ->отображение->окно».
П р и л о ж е н и я , использующие S D I (Single Document Interface) и л и
M D I (Multi Document Inter-face) интерфейс соответственно, называются
SDI-приложением
и MDI-приложением.
Такие п р и л о ж е н и я относятся к
п р и л о ж е н и я м с архитектурой «документ-отображение»
(document/view).
Создание приложения с архитектурой «документ-отображение»
П р и создании приложения, использующего архитектуру «документотображение», к а к правило, д о л ж н ы быть в ы п о л н е н ы следующие шаги:
1.
созданы ресурсы, используемые в шаблоне документа;
2.
реализован класс приложения (производный от CWinApp). Переопре¬
делен в этом классе метод I n i t I n s t a n c e ;
3.
в методе InitInstance созданы шаблоны всех типов используемых докумен
тов и добавлены в список шаблонов. Класс CWinApp имеет переменную
«член класса m_pDocManager», используемую для доступа к списку шаблонов;
4.
в методе I n i t I n s t a n c e создан объект «окно-рамка» класса, наследуе
мого от класса CMDIFrameWnd или CMDIChildWnd, и д а н н о е окно отобра
ж е н о к а к главное о к н о приложения;
5.
в таблицу сообщений добавлены входы, которые описывают обработ
ку сообщений, поступающих при открытии или сохранении файла;
6.
создан объект «приложение»;
7.
реализован класс документа, производный от CDocument. Переопре
делены методы OnNewDocument и S e r i a l i z e ;
8.
реализован класс о к н а - р а м к и , производный от CMDIFrameWnd или
CMDIChildWnd;
204
Лекция 20
9.
Библиотека классов MFC среды проектирования
Visual Studio .NET. SDI и MDI приложения
реализован класс отображения, производный от CView или его по¬
томков.
Управление документом
Для реализации управления д а н н ы м и документа первоначально не¬
обходимо выполнить следующие шаги:
1.
Для каждого типа документов объявить класс, производный от клас¬
са CDocument.
2.
3.
4.
Для хранения данных объявить переменные класса документа.
Переопределить в производном классе документа метод Ser i a l i z e
класса CDocument. Метод Se r i a l i z e реализует чтение и запись данных
документа с диска.
Для выполнения стандартных операций над документом следует до¬
полнительно переопределить методы базового класса, такие как
OnNewDocument, OnOpenDocument и DeleteContents.
Д а н н ы е документа хранятся в переменных класса документа. Б и б л и
отека M F C содержит ряд классов, инкапсулирующих работу с различны
ми наборами данных, включая следующие классы:
• CString
• CObList
• CByteArray
• CStringList
• CMapWordToPrt
Для в ы п о л н е н и я операций над элементами данных в класс докумен
та добавляются требуемые методы.
При создании объекта «отображение» формируется указатель на доку
мент, используемый отображением для доступа к объекту «документ» (его
методам и переменным). Этот указатель может быть получен объектом ото
бражения вызовом метода GetDocument класса CView. Отображение использу
ет данные, хранимые в классе документа, для их отображения и изменения.
Работа с о т о б р а ж е н и я м и
Классы отображений
Для вывода данных на различные графические устройства использу
ются классы отображений. Базовым классом всех таких классов является
класс Cview, производный от класса CWnd.
Библиотека M F C , кроме класса Cview, предоставляет широкий набор
классов отображения, наследуемых от CView, включая следующие классы:
205
Курс
Введение в программирование
• C S c r o l l V i e w — для автоматической прокрутки и масштабирования
отображения.
• CFo rmView — для отображения ф о р м , содержащих элементы управле
ния. Объект CFo rmView создается на основе ресурса диалога.
• C C t r l V i e w — б а з о в ы й класс д л я к л а с с о в CEditView, CTreeView,
CListView, CEditView и CRichEditView. Эти классы позволяют исполь
зовать архитектуру «документ-отображение» для некоторых элемен
тов управления Windows.
• CEditView — для отображения, реализующего свойства поля редакти
рования. Объект класса CEditView реализует работу простого тексто¬
вого редактора.
• CRichEditView — для отображения, содержащего объект CRichEditCt r l .
Этот класс отображения реализует свойства окна редактирования и
позволяет управлять форматированием текста.
• C L i s t V i e w — для отображения, содержащего объект C l i s t C t r l .
• CTreeView — для отображения, содержащего объект C t r e e C t r l .
• CHtmlView — для отображения, использующего WEB-броузер. Д а н
н ы й класс позволяет просматривать Internet-страницы и папки ло¬
кальной файловой системы, а также может быть использован как
контейнер для активного документа.
• CRecordView и CDaoRecordView — для отображения ф о р м , которые с о
держат э л е м е н т ы у п р а в л е н и я , с в я з а н н ы е с п о л я м и объекта
CRecordset или CDaoRecordset, что отображают таблицы баз данных.
• COleDBRecordView — для отображения ф о р м , которые содержат эле
менты управления, связанные с полями объекта CRowset. Этот класс
применяется для доступа к д а н н ы м средств O L E D B .
Реализация интерфейса пользователя
Классы отображений содержат набор методов, которые выполняют
обработку событий, и н и ц и и р о в а н н ы х пользователем. Переопределение
этих методов позволяет задавать:
• обработку сообщений Windows от м ы ш и и от клавиатуры;
• обработку выполнения пунктов м е н ю , нажатия к н о п о к инструмен
тария и клавиш-акселераторов.
Реализация интерфейса пользователя может включать в себя обра¬
ботку:
• определяемых пользователем пунктов м е н ю ;
• пунктов меню, определяющих стандартные действия, такие как
Edit|Copy, Edit|Cut и Edit|Paste.
M F C поддерживает реализацию трех типов интерфейса для отобра
ж е н и я одного документа посредством нескольких отображений:
206
Библиотека классов MFC среды проектирования
Visual Studio .NET. SDI и MDI приложения
Лекция 20
• Отображение объектов одного класса в отдельных окнах документа
(поддержка команды Window| New).
• Отображение объектов одного класса в одном разделенном окне до¬
кумента (поддержка команды Window|Split). Создается несколько
объектов отображения одного класса.
• Отображение объектов различных классов в одном окне документа.
Документ
Поддержка работы с разделенным о к н о м реализована в классе
CSplitterWnd. Разделенным о к н о м является обычное окно, разбитое на
несколько панелей ( окон) и содержащее один и тот же документ.
207
Курс
Введение в программирование
Ц и к л ж и з н и документа (а совместно с н и м — и о к н а - р а м к и , и отоб
ражения) в M D I - п р и л о ж е н и и состоит из:
1.
вызова конструктора документа;
2.
вызова метода OnNewDocument или OnOpenDocument для каждого нового
документа;
3.
отображения и обработки документа;
4.
удаления данных вызовом метода DeleteContents;
5.
вызова деструктора документа.
Ц и к л ж и з н и д о к у м е н т а (а с о в м е с т н о с н и м — и о к н а - р а м к и и
о т о б р а ж е н и я ) в S D I - п р и л о ж е н и и о т л и ч а е т с я т е м , что в ы з о в конст¬
руктора происходит только один раз при первоначальном создании
д о к у м е н т а ; а н а л о г и ч н о и п р о х о д и т в ы з о в деструктора. А д л я к а ж д о г о
повторно создаваемого или открываемого документа выполняются
т о л ь к о э т а п ы 2-3-4.
Класс CView
Класс CView реализует основные возможности для работы с отобра
ж е н и я м и . О т н о ш е н и я между классом отображения, классом о к н а - р а м к и
и классом документа устанавливаются объектом CDocTemplate. Вызов к о н
структора нового отображения и сопоставление его документу в ы п о л н я
ется при открытии пользователем нового окна или при разделении суще¬
ствующего окна.
Один объект «отображение» может быть сопоставлен только одному
документу, однако один документ может иметь несколько сопоставлен¬
ных ему отображений.
Отображения обрабатывают сообщения, з а ф и к с и р о в а н н ы е в табли¬
це сообщений.
Отображения выполняют только показ данных документа и не отве
чают за сохранение данных. Документ предоставляет отображению необ¬
ходимую и н ф о р м а ц и ю о данных посредством вызова объектом «отобра¬
жение» методов документа. Для и н и ц и а л и з а ц и и отображения, сопостав
ленного документу, следует вызвать метод O n I n i t i a l U p d a t e .
Для внесения изменений в д а н н ы е отображение, к а к правило, в ы з ы
вает метод CDocument: : UpdateAllViews, который инициирует вызов методов
OnUpdate для всех других отображений. П о умолчанию реализация метода
OnUpdate определяет всю клиентскую область как недостоверную. Этот
метод может быть переопределен.
Для того чтобы использовать класс отображений Cview, следует:
1.
объявить производный класс от Cview;
2.
реализовать метод OnDraw, в ы п о л н я ю щ и й отображение экрана или
вывод на печать.
208
Лекция 20
Библиотека классов MFC среды проектирования
Visual Studio .NET. SDI и MDI приложения
В классе View объявлены методы для реализации архитектуры «доку
мент-отображение», включая следующие:
• DoPreparePrinting — метод вызывается и з переопределяемого метода
OnPreparePrinting для отображения диалогового окна Print и созда
н и я контекста устройства принтера.
• GetDocument — метод возвращает указатель на объект «документ», с о
поставленный данному отображению, или N U L L , если отображение
не пристыковано н и к какому документу;
• OnActivateView — метод вызывается п р и активации или деактивации
отображения;
• OnActivateFrame — метод вызывается при активации или деактивации
о к н а - р а м к и , содержащего отображение;
• OnUpdate — вызов этого метода инициируется при и з м е н е н и и отобра
ж е н и я документа.
Класс CFormView
Класс CFormView является базовым классом, используемым для отоб
р а ж е н и й , которые содержат элементы управления. Процесс создания
отображения CFormView аналогичен созданию диалогового окна.
Для того чтобы использовать отображение CFormView, следует:
1.
разработать в редакторе ресурсов шаблон диалогового окна;
2.
создать класс отображения. Например:
CMyFormView::CMyFormView() :
CFormView( CMyFormView::IDD );
3.
4.
5.
Переопределить метод OnUpdate;
реализовать методы, в ы п о л н я ю щ и е внесение изменений и з отобра
ж е н и я в документ;
сопоставить класс отображения с классом документа и о к н о м - р а м
кой, используя шаблон документа.
Шаблоны документа
Класс CDocTemplate
Класс CDocTemplate является абстрактным классом, предоставляю
щ и м основные возможности для работы с шаблонами документов.
Ш а б л о н документа определяет о т н о ш е н и е между тремя типами
классов.
209
Курс
Введение в программирование
• Класс документа, наследуемый от CDocument.
• Класс отображения, в ы п о л н я ю щ и й показ данных для указанного
класса документа. Класс отображения может быть наследован от
классов CView, C S c r o l l V i e w , CFormView, CEditView. (Класс CEditView м о
жет быть использован и напрямую.)
• Класс окна-рамки, содержащий отображение. Д л я S D I - п р и л о ж е н и й
этот класс наследуется от базового класса CFrameWnd, а для M D I - п р и ложений — от базового класса CMDIChildWnd. Однако, если в п р и л о
ж е н и и н е требуется переопределять поведение объекта «окно-рам¬
ка», то может быть создан объект «окно-рамка» непосредственно ба¬
зового класса, без объявления производных классов.
Для каждого типа документа в приложении создается отдельный
шаблон документа.
Класс CDocTemplate является абстрактным классом и, следовательно,
не может использоваться непосредственно для создания объектов. Обыч
н о д л я с о з д а н и я ш а б л о н о в п р и м е н я ю т с я его п р о и з в о д н ы е к л а с с ы
CSingleDocTemplate и CMultiDocTemplate. Однако м о ж н о создать и свой соб¬
ственный производный класс шаблона документа.
Например:
BEGIN
IDR MYTYPE "\nSheet\nWo rksheet\n
Worksheets (*.myc)\n.myc\
n MyCalcSheet\nMyCalc Worksheet"
END
BOOL CMyApp::InitInstance()
{
CMultiDocTemplate*
pDocTemplate;
pDocTemplate = new CMultiDocTemplate(
IDR_MYTYPE,
RUNTIME_CLASS(CMyDoc),
RUNTIME_CLASS(CMDIChildWnd),
RUNTIME_CLASS(CMyView));
AddDocTemplate(pDocTemplate);
// ...
}
Класс CSingleDocTemplate
Класс CSingleDocTemplate определяет шаблон документа для S D I приложений: одновременно может быть открыт только один документ;
документ отображается в главном окне. К а к правило, S D I - п р и л о ж е н и я
210
Лекция 20
Библиотека классов MFC среды проектирования
Visual Studio .NET. SDI и MDI приложения
поддерживают только один тип документа и, соответственно, имеют
только один объект CSingleDocTemplate.
Класс CMultiDocTemplate
Класс CMultiDocTemplate определяет шаблон документа для M D I приложений: одновременно может быть открыто несколько документов;
главное о к н о используется к а к пространство, в котором м о ж н о открывать
несколько о к о н - р а м о к для отображения документов.
Документы
Класс CDocument
Класс CDocument предоставляет основные возможности управления
документами.
Класс CDocument поддерживает набор стандартных операций над до¬
кументом: создание, загрузка, сохранение.
Каждый документ содержит указатель на сопоставленный ему объ¬
ект шаблона документа — для каждого типа документа; свой шаблон.
Пользователи взаимодействуют с документом посредством объекта
отображение (наследуемого от класса Cview — или его производных клас¬
сов), ассоциированного с документом.
Для работы с документами в приложении следует:
1.
создать производный класс от класса CDocument для каждого типа до¬
кумента;
2.
добавить переменные ч л е н ы класса для хранения данных каждого
документа;
3.
реализовать методы — ч л е н ы класса, в ы п о л н я ю щ и е чтение и изме¬
н е н и е данных документа.
Сериализация данных
Библиотека M F C реализует модель обмена д а н н ы м и между доку
ментом и файлом через специальный объект, называемый архивом. О б
м е н д а н н ы м и между приложением и архивом называется сериализацией.
Для обмена используется метод S e r i a l i z e класса документа.
П р и создании шаблона приложения с п о м о щ ь ю мастера AppWizard
м о ж н о добавить меню File, содержащее пункты Open, Save и Save as. Д л я
обработки каждого из указанных пунктов м е н ю , AppWizard вставляет в
программный код класса документа (производного от CDocument) пере211
Курс
Введение в программирование
определяемый метод S e r i a l i z e — либо для чтения состояния документа
из архива, либо для записи (загрузки) состояния документа в архив. П р о
граммисту необходимо только вставить в метод Se r i a l i z e код, выполняю¬
щ и й запись переменных в архив и чтение переменных из архива.
Для использования средств сериализации следует включить в объяв
л е н и е и реализацию класса макросы DECLARESERIAL и IMPLEMENTSERIAL со¬
ответственно.
Создание SDI-приложения
Начинать разработку приложения следует с ф о р м и р о в а н и я «макета»
приложения, который автоматически формируется мастером приложе¬
н и й AppWizard.
Мастер приложений M F C Application Wizard позволяет создавать
следующие ш а б л о н ы для приложений с архитектурой «документ-отобра¬
жение»:
• Single document — приложения с SDI-интерфейсом.
• Multiple documents — приложения с MDI-интерфейсом,
поддержива
ю щ и е только одно о к н о верхнего уровня.
Мастер приложений позволяет последовательно формировать ш а б
лон S D I приложения (Single Document Interface), включая или н е включая
в него поддержку таких элементов, как: доступ к и н ф о р м а ц и и из баз дан¬
ных, реализация возможностей контейнера или сервера, п р и м е н е н и е
O L E , использование элементов ActiveX, а также реализацию встроенной
панели инструментов, строки состояния, некоторых пунктов меню.
Так, п р и ф о р м и р о в а н и и S D I приложения будут созданы следующие
классы:
• производный класс от класса приложения CApp;
• класс р а м к и окна;
• класс документа (производный от CDocument);
• класс отображения (производный от CView).
Далее приводится код основных фрагментов S D I - п р и л о ж е н и я , авто¬
матически создаваемого мастером M F C Application Wizard.
// Appl.cpp : Файл реализации класса приложения
// (включает также код класса CAboutDlg для диалога About)
// Таблица сообщений класса CApplApp
BEGIN_MESSAGE_MAP(CApp1App, CWinApp)
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
ON_COMMAND(ID_FILE_PRINT_SETUP,
212
Лекция 20
Библиотека классов MFC среды проектирования
Visual Studio .NET. SDI и MDI приложения
CWinApp::OnFilePrintSetup)
END_MESSAGE_MAP()
CApp1App::CApp1App()
{ }
CApplApp theApp;
BOOL CApp1App::InitInstance()
{
// Конструктор
// Объект приложение
// Первый выполняемый метод
//приложени я
CWinApp::InitInstance();
// Регистрация шаблонов документа
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate( // Строка
//описани шаблона
IDRMAINFRAME,
RUNTIME_CLASS(CApp1Doc),
RUNTIME_CLASS(CMainFrame), // Главное окно
// SDI приложени я
RUNTIME_CLASS(CApp1View));
AddDocTemplate(pDocTemplate);
m_pMainWnd->ShowWindow(SW_SHOW); // Отображение
// главного окна приложени я
m_pMainWnd->UpdateWindow();
return TRUE;
}
// Класс CAboutDlg, реализующий диалог About
c l a s s CAboutDlg : p u b l i c CDialog
{public:
CAboutDlg();
enum { IDD = IDD_ABOUTBOX }; // Идентификатор ресурса диалога
protected:
v i r t u a l v o i d DoDataExchange(CDataExchange* pDX);
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{}
v o i d CAboutDlg::DoDataExchange(CDataExchange* pDX)
{ CDialog::DoDataExchange(pDX);}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) // Таблица сообщений
END_MESSAGE_MAP()
v o i d CApp1App::OnAppAbout() // Обработчик команды меню About
{
CAboutDlg aboutDlg;
aboutDlg.DoModal(); // Отображение модального диалога
}
213
Курс
Введение в программирование
// App1Doc.cpp : файл реализации класса документа CApp1Doc
IMPLEMENT_DYNCREATE(CApp1Doc, CDocument)
BEGIN_MESSAGE_MAP(CApp1Doc, CDocument) // Таблица сообщений
END_MESSAGE_MAP()
CApp1Doc::CApp1Doc()
{}
CApp1Doc::~CApp1Doc(){ }
BOOL CApp1Doc::OnNewDocument() // Переопределение метода,
{
// вызываемого при открытии документа
if
(!CDocument::OnNewDocument())
return FALSE;
// Место для добавления кода инициализации документа
return TRUE;
}
v o i d CApp1Doc::Serialize(CArchive& a r )
// Сериализация
{ i f (ar.IsStor ing())
{
// Место для добавления кода сохранения
}
else
{
// Место дл
добавлени
кода загрузки
}
}
// App1View.cpp : файл реализации класса CApp1View
IMPLEMENT_DYNCREATE(CApp1View, CView)
BEGIN_MESSAGE_MAP(CApp1View,
CView)
// Таблица сообщений
ON_COMMAND(ID_FILE_PRINT, C V i e w : : O n F i l e P r i n t )
ON_COMMAND(ID_FILE_PRINT_DIRECT, C V i e w : : O n F i l e P r i n t )
ON_COMMAND(ID_FILE_PRINT_PREVIEW, C V i e w : : O n F i l e P r i n t P r e v i e w )
END_MESSAGE_MAP()
CApp1View::CApp1View() { }
CApp1View::~CApp1View() { }
BOOL CApp1View::PreCreateWindow(CREATESTRUCT& c s )
{ return CView::PreCreateWindow(cs); }
v o i d CApp1View::OnDraw(CDC* /*pDC*/)
{ CApp1Doc* pDoc = GetDocument(); // Указатель на документ
ASSERT_VALID(pDoc);
}
BOOL CApp1View::OnPreparePrinting(CPrintInfo*
pInfo)
{ return D o P r e p a r e P r i n t i n g ( p I n f o ) ; // Действие по умолчанию
}
v o i d CApp1View::OnBeginPr inting(CDC* /*pDC*/, C P r i n t I n f o *
/*pInfo*/) { }
v o i d CApp1View::OnEndPr inting(CDC* /*pDC*/, C P r i n t I n f o * / * p I n f o * / )
214
Лекция 20
Библиотека классов MFC среды проектирования
Visual Studio .NET. SDI и MDI приложения
{ }
// MainFrm.cpp : файл реализации класса CMainFrame
IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
BEGINMESSAGE_MAP(CMainFrame, CFrameWnd) //Таблица сообщений
ON_WM_CREATE()
END_MESSAGE_MAP()
s t a t i c UINT i n d i c a t o r s [ ] =
{ ID_SEPARATOR,
// Идентификаторы ресурсов
ID_INDICATOR_CAPS,
// для строки состояния
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
CMainFrame::CMainFrame() {
}
CMainFrame::~CMainFrame() {
}
// Обработчик сообщени , получаемого при создани окна
i n t CMainFrame::OnCreate(LPCREATESTRUCT l p C r e a t e S t r u c t )
{ i f (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
return 0;
}
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& c s )
{ i f ( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
return TRUE;
}
215
Курс
Введение в программирование
Л е к ц и я 2 1 . Б и б л и о т е к а к л а с с о в MFC с р е д ы
п р о е к т и р о в а н и я Visual S t u d i o .NET.
Элементы управления
Элементы управления
Библиотека M F C содержит ш и р о к и й набор классов элементов у п
равления. Элементы управления, отображаемые л ю б ы м окном, предва
рительно должны быть добавлены в ресурс диалога. Это выполняется в
редакторе ресурсов среды проектирования Visual Studio .NET.
Все о к о н н ы е элементы управления наследуются от класса CWnd. Н а
следующей схеме представлен список классов элементов управления, н а
следуемых от CWnd.
C W n d
1 CAnimateCtrl |
1
CBotton
|
HCBitmapBotton |
1 COleControl I
CComboBox
HCComboBoxEx
[CProgressCtrll
iCDateTimeCtrl |
[CRichEditCtrl!
CEdit
1 CScrollBar |
1 CHeaderCtrl |
1 CSliderCtrl |
1
1
j
1 CListCtrl
[CMonthCalCtrl!
1 CReBarCtrl ]
[CSpinBottonCtrll
iCHtmlEditCtrlBasel
CStatic
iCHtmlEditCtrll
1
1 CHotKeyCtrl |
[CStatusBarCtrll
iCIPAddressCtrll
1
CLinkCtrl
1
CTabCtrl
[ CToolBarCtrl |
1
CListBox
1 CToolTipCtrl |
CTreeCtrl
—ICCheckListBox|
HCDragListBox |
В окне Resource View все ресурсы каждого проекта отображаются в
виде иерархического дерева с узлами, соответствующими типам исполь
зуемых ресурсов. В каждом узле расположены ресурсы одного типа. Так,
узел Dialog содержит все ресурсы-диалоги, используемые в приложении.
К а ж д ы й ресурс имеет свой идентификатор ресурса, используемый
ф у н к ц и я м и библиотеки M F C для доступа к данному ресурсу.
216
Лекция 21
Библиотека классов MFC среды проектирования
Visual Studio .NET. элементы управления
Редактор ресурсов
В редакторе ресурсов диалога м о ж н о выполнить настройку в н е ш н е
го вида и поведение диалога, а также всех элементов управления, р а с п о
ложенных в нем.
Для задания значений свойств и указания используемых обработчи
ков событий в редакторе ресурсов используется о к н о свойств Properties.
Оно состоит и з двух страниц: страницы свойств и страницы событий
(рис. 1). Каждая станица отображается к а к четыре вертикально располо
ж е н н ы х области. В первой верхней области расположен с п и с о к имен объ
ектов, содержащий идентификаторы всех используемых для данного д и
алога элементов управления, включая и идентификатор ресурса диалога.
Рис. 1. Окно свойств редактора ресурсов — страницы Properties
и Events
Под с п и с к о м и м е н объектов расположена панель инструментов, с о
держащая кнопки: для выбора типа просмотра свойств (по категориям
или в алфавитном порядке), переключения между страницей свойств
Properties, страницей событий для элементов управления Control Events и
страницей сообщений Messages (только для диалога).
217
Курс
Введение в программирование
В следующей области располагается панель значений — страница
Properties или страница Control Events. В н и ж н е й части окна свойств
Properties расположено поле, отображающее текущий выделенный эле¬
мент страницы свойств или страницы событий.
На странице событий представлены идентификаторы всех элемен
тов управления диалога и список допустимых для каждого элемента уп
равления сообщений. Если обработчик сообщения создан, то в поле
справа от и м е н и сообщения указывается имя метода — обработчика д а н
ного сообщения.
П р и создании посредством окна свойств нового метода — обработ¬
ч и к а события в заголовочный файл будет добавлено объявление нового
метода — обработчика события, в файл реализации вставлен код описа
н и я метода, а в таблицу сообщений — новый вход для данного сообще
ния.
Доступные элементы управления отображаются в редакторе ресур
сов в о к н е Toolbox. Для того чтобы расположить элемент управления в ди¬
алоге, достаточно выделить этот компонент на вкладке Dialog Editor окна
Toolbox, а затем щелкнуть м ы ш ь ю в требуемом месте разрабатываемого
диалогового окна. В шаблон диалога м о ж н о встроить любой элемент уп¬
равления, расположенный в о к н е Toolbox (рис. 2).
Вкладка Dialog Editor окна Toolbox содержит к н о п к и для следующих
элементов управления (сверху вниз):
• Pointer — курсор, используемый для выбора элементов управления в
шаблоне диалога.
• Botton — кнопка.
• Check Box — флажок.
• Edit Control — текстовое поле.
• Combo Box — о к н о комбинированного списка.
• List Box — о к н о списка.
• Group Box — рамка группы кнопок.
• Radio Button — радиокнопка.
• StaticText — статический текст.
• Picture Control — рисунок.
• Horizontal Scroll Bar — горизонтальная линейка прокрутки.
• Vertical Scroll Bar — вертикальная линейка прокрутки.
• Slider Control — маркер (слайдер).
• Spin Control — элемент прокрутки.
• Progress Control — шкала и н д и к а ц и и .
• Hot Key — определение клавиш-акселераторов.
• List Control — список.
• Tree Control — элемент управления дерево.
• Tab Control — вкладка.
218
Лекция 21
Библиотека классов MFC среды проектирования
Visual Studio .NET. элементы управления
Рис. 2. Панель элементов управления
• Animation Control — элемент управления анимация.
• Rich Edit 2.0 Control — окно редактирования с элементами ф о р м а т и
рования.
• Date Time Picker — определение данных в формате даты и времени.
• M o n t h Calendar Control — календарь.
• IP Address Controls — определение IP-адреса.
• Extended Combo Box — к о м б и н и р о в а н н ы й список с поддержкой и з о
бражений.
• Custom Control — настраиваемый элемент управления.
219
Курс
Введение в программирование
Choose Toolbox Items
| ? || X |
Рис.3. Диалог Choose Toolbox Items
С п и с о к отображаемых элементов управления в окне Toolbox м о ж н о
редактировать. Д л я этого следует в ы п о л н и т ь команду м е н ю Tools | Choose
Toolbox Items и выбрать добавляемые элементы управления (рис. 3).
Работа с элементами управления
К а ж д ы й элемент управления имеет свой набор атрибутов, называе
мых также свойствами элемента управления.
И з м е н е н и е атрибутов элемента управления в процессе в ы п о л н е н и я
приложения происходит и л и под воздействием пользователя н а д а н н ы й
элемент управления, и л и программным путем.
Поведение элемента управления определяется его методами — обра
ботчиками событий.
Так к а к все элементы управления реализуются классами, производ
н ы м и от CWnd, то о н и являются о к о н н ы м и объектами. К а к и д л я всех
оконных объектов, процесс создания включает в себя два этапа:
• создание элемента управления (например, размещение его в шабло
не диалога);
• связывание его с объектом и л и переменной.
Если элемент управления не требуется изменять в процессе выпол
н е н и я приложения, то для него можно н е выполнять связывание с объек¬
том и л и с переменной.
220
Лекция 21
Библиотека классов MFC среды проектирования
Visual Studio .NET. элементы управления
Все элементы управления, встраиваемые в диалоговые окна, м о ж н о
подразделить на о б щ и е и ActiveX-элементы управления. Библиотека
M F C поддерживает к а к те, так и другие, инкапсулируя их свойства и по¬
ведение в соответствующих классах.
И н и ц и а л и з а ц и ю элементов управления м о ж н о выполнять в методе
O n I n i t D i a l o g класса диалога.
Чтобы изменять значения, отображаемые элементами управления,
или использовать значения, определяемые посредством действий пользо
вателя, приложению нужно иметь доступ к элементам управления.
Доступ к элементам управления может быть реализован различными
способами:
• элемент управления связывается с некоторой переменной;
• элемент управления связывается с объектом соответствующего клас
са, и для работы с н и м используются методы этого класса;
• элемент управления н е связывается н и с каким объектом, а для д о
ступа к нему используется его идентификатор (отображаемый на
странице свойств);
• объявляется переменная, инициируемая указателем на элемент у п
равления.
Указатель на элемент управления м о ж н о получить вызовом метода
CWnd: :GetDlgItem с заданным в качестве параметра идентификатора эле
мента управления.
Например:
// 1. Инициализация указателем:
C E d i t * p E d i t l = ( C E d i t * ) GetDlgItem(IDC_EDIT1);
// Конструкция pMyStat-> Metod() позволяет вызывать
// любые методы класса
// 2. Доступ по идентификатору:
SetDlgItemText(IDC_EDIT1,
L"12345");
Для связывания элемента управления с переменной или объектом
соответствующего класса м о ж н о и с п о л ь з о в а т ь диалог Add Member
Variable Wizard (рис. 4), в ы з ы в а е м ы й к о м а н д о й к о н т е к с т н о г о м е н ю Add
Variable.
Ф л а ж о к Control variable определяет способ использования создавае¬
мой переменной:
• при установленном флажке связь будет осуществляться с объектом
соответствующего класса;
• п р и снятом флажке устанавливается связь с переменной и обмен
д а н н ы м и выполняется DDX-методами, автоматически добавляемы
ми в переопределяемый метод DoDataExchange. Метод DoDataExchange
221
Курс
Введение в программирование
ш
Add Member Variable Wizard - D2
Welcome to the Add Member Variable Wizard
•J
Access:
[^1 C o n t r o l v a r i a b l e
Variable t y p e :
CEdit
Control ID:
v
Variable n a m e :
1
Category:
v
IDC_EDIT1
1
IEOIT
1 1
Max value:
Min v a l u e :
1
1
1
, c p p file:
. h File:
C o m m e n t (// n o t a t i o n n o t r e q u i r e d ) ;
•I
| Control
Max chars:
C o n t r o l ty_pe:
1
IP 1
IE
1
Finish
Cancel
Рис. 4. Диалог A d d Member Variable
вызывается методом UpdateData, указывающим в качестве параметра
направление обмена д а н н ы м и : и з переменной в элемент управления
или наоборот.
Класс CEdit
К л а с с CEdit о б е с п е ч и в а е т ф у н к ц и о н и р о в а н и е э л е м е н т а у п р а в
л е н и я «окно редактирования»,
н а з ы в а е м о е т а к ж е текстовым
полем.
Окно редактирования может быть к а к однострочным, так и многост
рочным. Иногда однострочное окно редактирования также называ
ю т полем ввода.
Д л я с о з д а н и я м н о г о с т р о ч н о г о о к н а р е д а к т и р о в а н и я следует уста
н о в и т ь з н а ч е н и е свойства Multilin р а в н ы м True. Д л я у с т а н о в к и р а з б и е
н и я н а с т р о к и с и с п о л ь з о в а н и е м м я г к о г о к о н ц а с т р о к и следует устано
вить свойство Auto HScroll. П р и м я г к о м к о н ц е с т р о к и , в отличие от ж е
сткого, о к н о р е д а к т и р о в а н и я отображает р а з д е л е н и е н а с т р о к и , н е
в с т а в л я я н е п о с р е д с т в е н н о в с а м текст с и м в о л ы к о н ц а с т р о к и и перево¬
да к а р е т к и .
П р и д в о й н о м щелчке м ы ш и н а элементе управления выполняется
автоматическая вставка метода обработчика сообщения OnEnChangeEdit.
Таблица сообщений родительского окна может содержать д л я эле
мента управления «окно редактирования» вызовы следующих стандарт
н ы х обработчиков сообщений:
222
Лекция 21
Библиотека классов MFC среды проектирования
Visual Studio .NET. элементы управления
• ON_EN_CHANGE — пользователь изменил текст в о к н е редактирования.
• ON_EN_ERRSPACE — недостаточно памяти.
• ON_EN_HSCROLL — пользователь щелкнул на горизонтальной л и н е й к е
прокрутки окна редактирования.
• ON_EN_KILLFOCUS — окно редактирование теряет фокус.
• ON_EN_MAXTEXT — текущая п о з и ц и я вставки превысила указанное для
окна редактирования число символов; либо не установлен стиль
ES_AUTOHSCROLL, а число вставляемых символов превышает ш и р и н у
окна редактирования или общее число строк превышает высоту ок
на редактирования.
• ON_EN_SETFOCUS — о к н о редактирования получает фокус ввода.
• ON_EN_UPDATE — пользователь изменил текст в о к н е редактирования;
(а в чем отличие от п.2? — Ред.)
• ON_EN_VSCROLL — пользователь щелкнул на вертикальной л и н е й к е
прокрутки окна редактирования.
Класс CEdit предоставляет ш и р о к и й набор методов для работы с ок
н о м редактирования, включая следующие:
• CanUndo — метод возвращает ненулевое значение, если последнее и з
менение в о к н е редактирования м о ж н о отменить, и 0 — если изме
н е н и е отменить нельзя.
• CharFromPos — метод возвращает номер символа в строке и строки
(начиная с 0) для символа, наиболее близко расположенного к ука¬
занной параметром точке.
• Clear — метод удаляет в окне редактирования текущее выделение текста.
• Copy — метод копирует текущее выделение текста из окна редактиро
вания в буфер промежуточного хранения.
• Cut — метод удаляет текущее выделение текста из окна редактирова
н и я и копирует его в буфер промежуточного хранения.
• Paste — метод выполняет вставку данных из буфера промежуточно
го хранения в текущую позицию окна редактирования.
• G e t F i r s t V i s i b l e L i n e — метод возвращает номер первой отображае
мой строки в о к н е редактирования.
• GetLine — метод копирует указанную строку текста (без нулевого
символа) из окна редактирования в буфер и при успешном заверше¬
н и и возвращают количество скопированных байтов.
• GetLineCount — метод возвращает количество строк текста в м н о г о
строчном о к н е редактирования.
Например:
extern C E d i t * pmyEdit;
i n t i , nLineCount = pmyEdit->GetLineCount();
CString strText, s t r L i n e ;
223
Курс
Введение в программирование
f o r ( i = 0 ; i < nLineCount;
{
// Получение длины строки i
i n t l e n = pmyEdit->LineLength(pmyEdit->LineIndex( i ) ) ;
pmyEdit->GetLine( i , s t r T e x t . G e t B u f f e r ( l e n ) , l e n ) ;
strText.ReleaseBuffer(len);
strLine.Format(TEXT("line
%d: ' % s ' \ n " ) , i , s t r T e x t ) ;
cout << s t r L i n e ;
}
• GetSel — метод определяет п о з и ц и ю первого и последнего символа
выделенного фрагмента текста.
Например:
extern
C E d i t * pmyEdit;
// Выделить все символы, следующие за текущим
// выделенным фрагментом
DWORD dwSel = pmyEdit->GetSel();
// Определение
// позиций текущего выделения
pmyEdit->SetSel(HIWORD(dwSel),
-1); // HIWORD(dwSel) // позици первого невыделенного символа,
// следующего за выделением
• L i m i t T e x t — метод устанавливает максимально допустимую длину (в
байтах) вводимого пользователем текста.
• LineIndex — метод возвращает н о м е р первого символа в указанной
строке, а при значении параметра, равном -1 — номер первого сим¬
вола в текущей строке.
• LineLength — метод возвращает длину строки.
• ReplaceSel — метод выполняет замену выделенного фрагмента текс¬
та на указанную строку.
• SetPasswordChar — метод устанавливает символ, отображаемый при
вводе пароля, вместо любого вводимого пользователем символа.
• S e t S e l — метод выполняет выделение в о к н е редактирования указан¬
ного фрагмента текста.
Класс CStatic
Класс C S t a t i c реализует работу со статическим текстом (меткой).
Этот элемент управления предназначается для отображения различных
надписей и не может непосредственно редактироваться пользователем.
Содержание элемента управления Static Box определяется на этапе проек224
Лекция 21
Библиотека классов MFC среды проектирования
Visual Studio .NET. элементы управления
тирования свойством Caption и в дальнейшем может изменяться только
программным путем.
Выполнить связывание элемента управления «статический текст»
м о ж н о с переменной типа CString или объектом класса CStatic.
Свойство Border определяет, что вокруг элемента управления будет
отображаться рамка.
Свойство Transparent определяет, является ли фон элемента прозрачным.
Класс CButton
Класс CButton применяется для работы со следующими элементами
управления:
• командная кнопка;
• флажок;
• радиокнопка (переключатель).
Элемент управления «кнопка», называемый также командная кноп
ка, как правило, используется для обработки сообщения B N C L I C K E D .
Свойство Default Button позволяет указать командную кнопку, уста¬
навливаемую как к н о п к а по умолчанию: нажатие пользователем клавиши
Enter интерпретируется как щелчок на данной кнопке.
Свойство Icon позволяет указать, что вместо текста будет отображе
на пиктограмма (стиль B S I C O N ) .
Свойство Bitmap позволяет указать, что вместо текста будет отобра
ж е н о изображение (стиль B S B I T M A P ) .
Свойство Multiline используется в том случае, если текст с л и ш к о м
д л и н н ы й , чтобы уместиться на к н о п к е в одну строку.
Для работы с элементом управления «кнопка» следует использовать
класс CButton.
Элемент управления «флажок Check Box» может иметь два или три со
стояния: включенное, выключенное или неопределенное (необязательно).
К р о м е возможности связывания флажка с объектом типа CButton,
ф л а ж о к м о ж н о связать с переменной типа B O O L .
Свойство Auto позволяет создавать элемент управления, переключе
н и е состояний (включен/выключен) которого происходит автоматически
при щелчке м ы ш ь ю .
Свойство Tri-state используется для создания элемента управления
«флажок», и м е ю щ е г о три с о с т о я н и я . О д н о в р е м е н н о с с о с т о я н и я м и
«включен» или «выключен», используется состояние «неопределен», в к о
тором флажок выглядит «посеревшим».
Если значение свойства Push Like установлено равным True, то со¬
здается элемент управления «флажок», отображаемый как командная
225
Курс
Введение в программирование
кнопка: п р и нажатии флажок имеет вид вдавленной к н о п к и , а при н е н а жатом состоянии — выпуклой.
Свойство Flat определяет, будет л и создаваемый элемент управления
иметь вид плоской к н о п к и .
Элемент у п р а в л е н и я «радиокнопка» (Radio Button) а н а л о г и ч е н
флажку, н о н е может иметь неопределенного состояния. Также при объе¬
д и н е н и и несколько р а д и о к н о п о к в группу только одна и з н и х может
иметь включенное состояние.
К р о м е возможности связывания флажка с объектом типа CButton,
радиокнопку м о ж н о связать с переменной типа B O O L .
П р и использовании класса CButton тип к н о п к и м о ж н о определить ее
стилем, указываемым в методе Create п р и создании к н о п к и . Класс
CButton наследуется классом CBitmapButton, реализующим к н о п к и с изоб
р а ж е н и я м и вместо текста.
Создать кнопку м о ж н о к а к с использованием редактора ресурсов,
так и непосредственно программным путем.
Если объект CButton создается расположенным в диалоговом окне,
то о н автоматически разрушается п р и закрытии пользователем этого диа¬
логового окна. Если ж е объект был создан динамически вызовом метода
new, то для его разрушения следует вызвать метод delete.
Класс CButton предоставляет ряд методов, включая следующие:
• Create — метод создает Windows-кнопку для объекта CButton и п р и
успешном завершении возвращает ненулевое значение. П р и вызове
метода к н о п к е могут быть присвоены следующие ф л а ж к и стиля
(оконного объекта):
WS_CHILD — устанавливается всегда;
WS_VISIBLE — видимая кнопка;
WS_DISABLED — недоступная кнопка;
WS_GROUP — используется для образования групп кнопок: устанавли
вается для первой к н о п к и группы;
WS_TABSTOP — устанавливается для включения к н о п к и в табулирован
н ы й порядок.
• GetCheck — метод определяет состояние кнопки (флажка или радио
к н о п к и ) , созданной к а к BS_AUTOCH ECKBOX, BS_AUTORADIOBUTTON,
BS_AUTO3STATE, BS_CHECKBOX, BS_RADIOBUTTON, BS_3STATE, и возвращает
одно из следующих значений:
0 — к н о п к а н е включена (не отмечена);
1 — к н о п к а включена (отмечена);
2 — к н о п к а находится в неопределенном состоянии (только
для к н о п о к , и м е ю щ и х ф л а ж к и стиля BS_3STATE и л и
BS_AUTO3STATE).
226
Лекция 21
Библиотека классов MFC среды проектирования
Visual Studio .NET. элементы управления
Для командных к н о п о к метод возвращает значение 0.
• GetState — метод определяет текущее состояние к н о п к и . Возвраща
емое значение формируется к а к к о м б и н а ц и я набора значений, в ы
деляемых с п о м о щ ь ю следующих масок:
0x0003 — определяет состояние к н о п к и - ф л а ж к а или радиокнопки:
0 — к н о п к а н е включена (не отмечена);
1 — к н о п к а отмечена;
2 — состояние к н о п к и н е определено.
0x0004 — определяет состояние выделения кнопки: при значении 0 —
кнопка не нажата (пользователь щелкнул на ней левой кнопкой мыши
и держит ее);
0x0008 — определяет фокус: при значении 1 — кнопка находится в фокусе.
• SetBitmap — метод «растровое изображение, отображаемое на дан¬
н о й кнопке».
Например:
CButton myButton;
// Создание кнопки с изображением
myButton.Create(_T("Кнопка 1"), WS_CHILD|WS_VISIBLE|BS_BITMAP,
CRect(10,10,60,50), pParentWnd, 1);
myButton.SetBitmap( ::LoadBitmap(NULL,
MAKEINTRESOURCE(OBM_CHECK)) );
• S e t B u t t o n S t y l e — метод изменяет стиль к н о п к и .
• SetCheck — метод устанавливает новое состояние к н о п к и - п е р е к л ю
чателя и л и радиокнопки.
Класс CListBox
Элемент управления List Box «окно списка», называемый иногда
просто списком, используется для работы с и н ф о р м а ц и е й , отображаемой
в виде списка. О к н о списка может быть реализовано к а к список с единич¬
н ы м или с множественным выбором.
Окно списка м о ж н о связать к а к с переменной типа C S t r i n g , так и с
объектом класса CListBox.
Свойство Selection позволяет устанавливать тип списка:
• Single (по умолчанию) — пользователь может выделить только один
элемент списка.
• Multiple — пользователь может одновременно выделить несколько
элементов списка. Выделение элементов (или снятие выделения)
осуществляется п р и щелчке или д в о й н о м щелчке м ы ш и .
227
Курс
Введение в программирование
• Extended — пользователь может одновременно выделить несколько
элементов списка. Выделение элементов (или снятие выделения)
осуществляется перемещением м ы ш и при нажатой кнопке.
• None — пользователь не может выделить н и одного элемента списка.
Класс C L i s t B o x предоставляет ш и р о к и й набор методов для работы со
списком, включая следующие:
GetCount — метод возвращает количество элементов в о к н е списка.
SetTopIndex — метод прокручивает о к н о списка к указанному эле
менту, отображая его первым видимым элементом.
Например:
extern C L i s t B o x * pmyListBox;
// Определение первым видимым элементом списка
// элемента,расположенного посередине списка
pmyListBox->SetTopIndex(pmyListBox->GetCount()/2);
• G e t T e x t — метод возвращает строку по указанному индексу элемента
списка.
Например:
extern C L i s t B o x * pmyListBox;
CString s t r , str2;
i n t n;
f o r ( i n t i=0; i < pmyListBox->GetCount(); i++)
{
n = pmyListBox->GetTextLen( i );
pmyListBox->GetText( i , s t r . G e t B u f f e r ( n ) );
str.ReleaseBuffer();
// Дампинг всех элементов списка ( # i f d e f DEBUG )
s t r 2 . F o r m a t ( _ T ( " i t e m %d: % s \ r \ n " ) , i ,
str.GetBuffer(0));
afxDump << s t r 2 ;
}
• S e t C u r S e l — метод выделяет указанный элемент списка и при необ¬
ходимости прокручивает о к н о списка так, чтобы выделенный эле¬
мент стал видимым.
• GetSelCount — метод возвращает общее количество выделенных эле¬
ментов в о к н е списка с множественным выбором.
• A d d S t r i n g — метод добавляет в о к н о списка н о в ы й элемент, содержа¬
щ и й указанную строку.
228
Лекция 21
Библиотека классов MFC среды проектирования
Visual Studio .NET. элементы управления
• D e l e t e S t r i n g — метод удаляет и з окна списка строку с соответствую¬
щ и м индексом.
• I n s e r t S t r i n g — метод вставляет в указанное место окна списка но¬
вый элемент, содержащий заданную строку.
• F i n d S t r i n g — метод выполняет поиск указанной строки в окне списка.
• ResetContent — метод удаляет все элементы окна списка.
Класс CAnimateCtrl
Класс CAnimateCtrl предоставляет ф у н к ц и и управления анимацией в
среде Windows.
Элемент управления, созданный к а к экземпляр данного класса, я в
ляется объектом анимации. Такой объект представляет из себя обычное
о к н о , в котором отображается некоторый клип, я в л я ю щ и й с я файлом в
формате AVI (Audio Video Interleaved). AVI-файл содержит последователь¬
н ы й набор битовых изображений. Объекты а н и м а ц и и могут показывать
только простые AVI-клипы.
Класс CComboBox
Класс CComboBox реализует ф у н к ц и о н и р о в а н и е комбинированного ок
на, иногда также называемого комбинированным окном списка.
К о м б и н и р о в а н н о е о к н о представляет собой элемент управления,
объединяющий о к н о списка с о к н о м редактирования и л и со статическим
элементом управления. О к н о списка при этом может иметь к а к распахну
тое (отображаемое постоянно), так и свернутое состояние (отображаемое
только п р и щелчке пользователя на стрелке вниз).
Выбранный элемент списка отображается в о к н е редактирования
или в о к н е статического элемента управления.
Метод GetLBText определяет строку текста, соответствующую ука
занному индексу элемента окна списка комбинированного окна. Метод
GetCurSel возвращает индекс выделенного элемента окна списка комби¬
нированного окна. Если выделенного элемента нет, то метод возвращает
значение CB_ERR.
Например:
extern CComboBox* pmyComboBox;
// Выбор следующего элемента в окне комбинированного списка
// после текущего элемента
i n t nIndex = pmyComboBox->GetCurSel();
// Индекс текущего
// элемента
i n t nCount = pmyComboBox->GetCount();
// Всего элементов
229
Курс
Введение в программирование
// в списке
if
((nIndex != CB_ERR) && (nCount > 1))
{
if
(++nIndex < nCount)
pmyComboBox->SetCurSel(nIndex);
else
pmyComboBox->SetCurSel(0);
}
Класс CRichEditCtrl
Элемент управления «окно расширенного редактирования» (rich edit
control) позволяет пользователю на только редактировать текст, в отличие
от элемента управления «окно редактирования», но также выполнять
форматирование символов и абзацев, встраивать OLE-объекты.
Д а н н ы й элемент управления обеспечивает программный интерфейс
для форматирования текста, при этом в приложении д о л ж н ы быть реали
зованы все к о м п о н е н т ы интерфейса пользователя, делающие доступны
ми сами операции форматирования.
Метод GetDefaultCharFormat позволяет получить атрибуты ф о р м а т и
рования символов по умолчанию. Атрибуты форматирования символов
определяются в структуре типа CHARFORMAT, а атрибуты форматирования
абзаца задаются в структуре типа PARAFORMAT. Метод GetLine копирует в бу¬
фер указанную строку текста.
Методы SetDefaultCharFormat и SetSelectionCharFormat позволяют ус
тановить атрибуты форматирования символов, используемые по умолча
н и ю или для выделенного фрагмента текста соответственно.
230
Лекция 22
Управление разработкой ПО
Л е к ц и я 2 2 . Б и б л и о т е к а к л а с с о в MFC с р е д ы
п р о е к т и р о в а н и я Visual Studio .NET.
Многостраничные диалоги
Создание многостраничных диалогов
Многостраничные диалоги отображаются как:
• окна наборов свойств (property sheets);
• диалоговые окна со вкладками (tab dialog boxes);
• мастера,
п р е д с т а в л я ю щ и е с о б о й последовательность с т р а н и ц
свойств.
П р и м е р о м мастеров могут служить мастера AppWizard, используе
м ы е для создания шаблона приложения. Д л я управления последователь
ностью страниц в мастерах используются к н о п к и Back, Next, Finish и
Cancel. Чтобы создать о к н о набора свойств к а к мастер, следует перед в ы
зовом метода DoModal вызвать метод SetWizardMode, а для доступа к к о
м а н д н ы м к н о п к а м использовать метод SetWizardButtons.
Многостраничный диалог может быть реализован с п о м о щ ь ю клас¬
са CPropertySheet, производного от CWnd. Объект класса CPropertySheet н а
зывается набором свойств или о к н о м набора свойств.
Каждая страница и з набора свойств может быть реализована объек
том типа CPropertyPage, производного от CDialog.
Д и а л о г о в о е о к н о класса CPropertyPage н а з ы в а е т с я
страницей
свойств.
Окно набора свойств представляет собой специальный вид диалого
вого окна, используемый для изменения атрибутов некоторого внешнего
объекта.
Окно набора свойств состоит и з трех частей:
• диалогового окна;
• одной или нескольких страниц свойств, показываемых попеременно;
• компонента «вкладка», содержащего заголовки вкладок для каждой
страницы.
Для того чтобы использовать в приложении многостраничный диа¬
лог, нужно выполнить следующие шаги:
1.
Создать в редакторе ресурсов шаблон диалога отдельно для каждой
страницы свойств.
Ш а б л о н ы диалогов могут иметь различный размер — п р и размеще¬
н и и окна набора свойств будет выбран размер наибольшего шаблона ди¬
алога.
На странице свойств окна Properties для каждого шаблона диалога
следует установить значения для свойств:
231
Курс
Введение в программирование
• Caption — содержит заголовок вкладки, отображаемый для текущей
страницы;
• S t y l e — имеет значение C h i l d ;
• Border — указывает стиль р а м к и T h i n ;
• T i t l e b a r — установлено р а в н ы м True;
• D i s a b l e d — установлено р а в н ы м True.
2.
Создать для каждого ш а б л о н а диалога к л а с с , п р о и з в о д н ы й от
CPropertyPage, и добавить в эти классы п е р е м е н н ы е - ч л е н ы класса,
используемые для доступа к странице свойств. Д л я каждой добавля¬
емой в набор свойств страницы создать по одному объекту класса,
производного от CpropertyPage.
3.
Создать в коде программы объект класса CPrope rtySheet. Вызвать для
к а ж д о й с т р а н и ц ы (типа п р о и з в о д н о г о от CPropertyPage) метод
CPropertySheet::AddPage.
6.
Показать о к н о набора свойств, вызвав метод CPropertySheet: :DoModal
или CPropertySheet::Create.
Чтобы выполнить обмен д а н н ы м и с о к н о м набора свойств, следует
создать переменные для доступа к элементам управления страниц свойств
и использовать D D X - и DDV-методы для обмена д а н н ы м и между э л е м е н
тами управления и п е р е м е н н ы м и класса окна страницы свойств.
Обмен д а н н ы м и для окна набора свойств следует выполнять отдель
н о для каждой страницы свойств.
Например:
v o i d CMyView::DoModalPropertySheet()
// Создание
// модального окна
{
// набора свойств с двумя страницами
CPropertySheet propsheet;// Создание объекта «диалог»
CMyPage1 page1;
// Создание объекта класса,
// производного от CPropertyPage
CMyPage2 page2;
//...
page1.m_nMember1 = m_nMember1;
// Обмен данными:
page1.m_nMember2 = m_nMember2;
// инициализаци
page2.m_strMember3 = m_strMember3; // переменных членов
//класса
propsheet.AddPage(&page1); // Добавление страницы свойств
propsheet.AddPage(&page2);
//...
i f (propsheeet.DoModal() == IDOK)
{
m_nMember1 = page1.m_nMember1;
232
Лекция 22
Управление разработкой ПО
m_nMember2 = page1.m_nMember2;
m_strMember3 = page2.m_strMember3;
GetDocument()->SetModifiedFlag();
GetDocument()->UpdateAllViews(NULL);
}
}
Класс CPropertySheet
Класс CPropertySheet инкапсулирует в о з м о ж н о с т и управления мно¬
г о с т р а н и ч н ы м диалогом.
Класс CPropertySheet предоставляет ряд методов, включая следую¬
щие:
• GetActiveIndex — м е т о д в о з в р а щ а е т и н д е к с т е к у щ е й с т р а н и ц ы
свойств.
• GetPageCount — метод возвращает количество с т р а н и ц свойств в о к н е
набора свойств.
• GetPage — метод возвращает указатель н а страницу свойств, задан¬
н у ю п о индексу.
• GetActivePage — метод возвращает указатель н а текущую активную
страницу свойств.
• SetActivePage — метод устанавливает новую текущую активную стра¬
ницу.
Например:
BOOL CMySheet::OnInitDialog() // Класс CMySheet
//наследует от CPropertySheet
{
BOOL bResult = C P r o p e r t y S h e e t : : O n I n i t D i a l o g ( ) ;
CFrameWnd* frame = (CFrameWnd*) AfxGetMainWnd();
CPSheetDoc* doc = (CPSheetDoc*) frame->GetActiveDocument();
SetActivePage(doc->m_LastActivePage); // Устанавливаем
// текущей последнюю активную страницу
return bResult;
}
BOOL CMyPropertySheet::OnCommand(WPARAM
wParam,
LPARAM lParam)
{ i f (LOWORD(wParam) == IDOK)
{
CFrameWnd* frame = (CFrameWnd*) AfxGetMainWnd();
CPSheetDoc* doc = (CPSheetDoc*)frame->GetActiveDocument();
// Сохранение индекса последней активной страницы:
233
Курс
Введение в программирование
doc->m_LastActivePage = GetPageIndex(GetActivePage());
// Или G e t A c t i v e I n d e x ( )
}
return CPropertySheet::OnCommand(wParam,
lParam);
}
• SetTitle — метод устанавливает заголовок для окна набора свойств;
• GetTabControl — метод возвращает указатель н а объект класса
CTabCtrl, обеспечивая доступ к элементу управления «вкладка».
• SetFinishText — метод устанавливает текст, отображаемый на ко¬
мандной к н о п к е Finish, и делает ее доступной.
• SetWizardButtons — метод устанавливает доступные командные к н о п
ки для мастера, которые задаются комбинацией следующих флажков:
PSWIZB_BACK, PSWIZB_NEXT, PSWIZB_FINISH, PSWIZB_DISABLEDFINISH.
• SetWizardMode — метод устанавливает, что о к н о набора свойств будет
мастером (при отображении окна вызовом метода D o M o d a l возвра
щаемые значения будут ID WIZFINISH или IDCANCEL).
Например:
CPropertySheet d l g ;
CPropertyPage page1, page2;
dlg.AddPage(&page1);
dlg.AddPage(&page2);
dlg.SetWizardMode();
dlg.DoModal();
• AddPage — метод добавляет в о к н о набора свойств указанную страни¬
цу свойств;
• RemovePage — метод удаляет указанную страницу свойств из окна на¬
бора свойств;
• PressButton — метод имитирует выбор в о к н е набора свойств указан¬
н о й командной к н о п к и .
Класс PRopertyPage
Объекты класса CPropertyPage представляют отдельные страницы
набора свойств. Непосредственным базовым классом для CPropertyPage
является класс CDialog.
Класс CPropertyPage предоставляет ряд методов, включая следующие:
• CancelToClose — метод вызывается для замены кнопки O K на кнопку Close.
• SetModif ied — метод делает командную кнопку Apply доступной или
недоступной.
234
Лекция 22
Управление разработкой ПО
• Q u e r y S i b l i n g s — метод используется для передачи сообщения другим
страницам набора свойств.
• OnCancel — метод вызывается средой выполнения при щелчке поль
зователя на командной к н о п к е Cancel.
• O n K i l l A c t i v e — метод вызывается средой выполнения при смене те¬
кущей активной страницы свойств.
• OnOK — метод вызывается средой в ы п о л н е н и я при щелчке пользова
теля на командной к н о п к е O K .
• OnSetActive — метод вызывается средой выполнения при выборе
пользователем новой активной текущей страницы.
• OnApply — метод вызывается средой выполнения при щелчке пользо
вателя на командных кнопках O K или Apply.
• OnWizardFinish — метод вызывается средой в ы п о л н е н и я при щелчке
пользователя на командной к н о п к е Finish.
Списки изображений
Класс CImageList
Класс CImageList реализует работу со списком одноразмерных изоб
р а ж е н и й . Его н е п о с р е д с т в е н н ы м б а з о в ы м к л а с с о м я в л я е т с я класс
CObject.
Методы класса CImageList позволяют более э ф ф е к т и в н о управлять
наборами больших и малых пиктограмм и наборами изображений.
Все изображения списка изображений хранятся в одном битовом
массиве в э к р а н н о м формате. Дополнительно список изображений может
включать монохромный битовый массив, который содержит маску, ис¬
пользуемую для отображения изображений с прозрачным ф о н о м .
Пиктограммы всегда содержат маску для отображения с прозрачным
фоном.
Создание объекта «список изображений» выполняется в два этапа.
1.
Вызывается конструктор класса CImageList.
2.
Вызывается метод Create, создающий с п и с о к изображений и при¬
стыковывающий его к объекту CImageList.
Например:
extern CImageList* pmyImageList;
pmyImageList->Create(32, 32, // Размер изображения
ILC_COLOR16,
// 16-битовый цвет
0,
// Первоначальное количество изображений
4);
235
Курс
Введение в программирование
Класс CImageList предоставляет ряд переменных и методов, включая
следующие:
• m_hImageList — указатель списка изображений, сопоставленного
данному объекту.
• Create — конструктор объекта.
• Attach — метод пристыковывает указанный с п и с о к изображений к
объекту типа CImageList.
• Add — метод используется для добавления нового изображения к
списку изображений.
Например:
extern CImageList* pmyImageList;
// Добавление к списку изображений двух пиктограмм
pmyImageList->Add(AfxGetApp()->LoadIcon(IDI_ICON1));
pmyImageList->Add(AfxGetApp()->LoadIcon(IDI_ICON2));
// Добавление изображени , в котором все черные
// пиксели устанавливаютс прозрачными
CBitmap bm;
bm. LoadBitmap(IDB_BITMAP1);
pmyImageList->Add(&bm, RGB(0, 0, 0 ) ) ;
• Replace — метод используется для удаления изображения из списка
изображений.
236
Лекция 23
Библиотека классов .NET Framework среды проектирования
VIsual Studio .NET. Формы Windows
Лекция 23. Библиотека классов .NET Framework с р е д ы
п р о е к т и р о в а н и я Visual Studio .NET. Ф о р м ы W i n d o w s
Приложения-диалоги
Создание формы
Ф о р м ы Windows реализуются набором классов из пространства и м е н
Systems.Windows.Forms.
Базовым классом для всех окон является класс Form.
Для создания приложения-диалога на я з ы к е С + + следует:
1.
В о к н е дизайнера создать диалоговую форму. Код, соответствующий
создаваемой форме, записывается в файл с расширением .h (напри¬
мер, Form1.h).
2.
В методе main файла приложения выполнить создание ф о р м ы вызо
вом метода Run объекта Application.
Например:
// D1.cpp : главный файл проекта.
#include " s t d a f x . h "
#include "Form1.h"
// Файл формы
using namespace D1;
[STAThreadAttribute]
i n t main(array<System::String "> " a r g s )
{
// создание окна формы
Application::Run(gcnew Form1());
return 0;
}
Оператор gcnew создает экземпляр управляемого типа. Результатом
в ы п о л н е н и я д а н н о й операции является дескриптор, указывающий на
объект управляемого типа. Для объявления переменной типа дескрипто
ра используется операция .
Доступ к свойствам и методам объекта через дескриптор выполняет
ся операцией ->.
А
Редактор формы
Редактор ф о р м ы позволяет в графическом режиме разместить на
ф о р м е все требуемые элементы управления, определить первоначальное
значение свойств этих элементов и создать для них обработчики событий.
237
Курс
Введение в программирование
П р и р а з м е щ е н и и в ф о р м е нового элемента управления соответству
ю щ и й код добавляется в ф а й л ф о р м ы . Аналогично для задания значения
каждого свойства в ф а й л ф о р м ы добавляется соответствующий s e t - м е т о д .
М е т о д ы - о б р а б о т ч и к и событий также п о м е щ а ю т с я в ф а й л ф о р м ы .
Следующий код представляет ф а й л ф о р м ы для ф о р м ы , в которую
добавлено два элемента управления — поле ввода и к о м а н д н а я к н о п к а :
namespace D1 {
// Подключение используемых пространств имен
using namespace System;
using namespace System::ComponentModel;
using namespace S y s t e m : : C o l l e c t i o n s ;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
// r e f c l a s s объявляет управляемый класс C++
p u b l i c r e f c l a s s Form1 :
p u b l i c System::Windows::Forms::Fo rm
{
public:
Form1(void){InitializeComponent();}
protected:
~Form1(){if (components) { d e l e t e components;}}
// Объявление элемента управления «кнопка»:
p r i v a t e : System::Windows::Forms::Button" button1;
// Объявление элемента управления
// «поле ввода»:
p r i v a t e : System::Windows::Forms::TextBox" textBox1;
// Объявление контейнера
private:System::ComponentModel::Container "components;
#pragma region Windows Form Designer generated code
// Формируетс дизайнером формы
void InitializeComponent(void)
{ // Создание объекта «кнопка»:
this->button1 =
(gcnew System::Windows::Forms::Button());
// Создание объекта «поле ввода»:
this->textBox1 =
(gcnew System::Windows::Forms::TextBox());
this->SuspendLayout(); // Временно
// приостанавливает событи компоновки до
238
Лекция 23
Библиотека классов .NET Framework среды проектирования
VIsual Studio .NET. Формы Windows
// вызова метода ResumeLayout или
// Задание свойств для кнопки button1
this->button1->Location =
System::Drawing::Point(427, 22);
this->button1->Name = L"button1";
this->button1->Size = System::Drawing::Size(75, 23);
this->button1->TabIndex = 0;
this->button1->Text = L"button1";
this->button1->UseVisualStyleBackColor = true;
// Определение обаботчика события C l i c k для кнопки
t h i s - > b u t t o n 1 - > C l i c k += gcnew System::EventHandler(
this,
&Form1::button1_Click);
// Задание свойств дл пол ввода textBox1
this->textBox1->Location =
System::Drawing::Point(80, 25);
this->textBox1->Name = L"textBox1";
this->textBox1->Size =
System::Drawing::Size(100, 20);
this->textBox1->TabIndex = 1;
// Задание свойств дл формы Form1
this->AutoScaleDimensions =
System::Drawing::SizeF(6, 13);
this->AutoScaleMode =
System::Windows::Forms::AutoScaleMode::Font;
t h i s - > C l i e n t S i z e = System::Drawing::Size(548, 266);
..// Добавление в форму элементов управления
this->Controls->Add(this->textBox1);
this->Controls->Add(this->button1);
this->Name = L"Form1";
this->Text = L"Form1";
this->ResumeLayout(false);
this->PerformLayout();
}
#pragma endregion
// Обработчик событи дл кнопки
pr i v a t e : System::Void b u t t o n 1 _ C l i c k (
System::Object"
sender,
System::EventArgs"
e)
{this->textBox1->Text = L"123456"; }
}; // Конец реализации класса
}
// Конец пространства имен D1
239
Курс
Введение в программирование
П р и создании проекта п р и л о ж е н и я для языка C# сразу создается д и
алоговая форма. Автоматически формируемое приложение включает в се
бя файлы, приведенные на рис. 1.
Рис. 1. Ф а й л ы проекта для C#
Ф а й л Program.cs — это главный ф а й л приложения, содержащий м е
тод main. В этот ф а й л по умолчанию вставляется следующий код:
using System;
using
using
System.Collections.Generic;
System.Windows.Forms;
namespace D_1
{
s t a t i c c l a s s Program
{ [STAThread]
s t a t i c v o i d Main()
{
240
Библиотека классов .NET Framework среды проектирования
VIsual Studio .NET. Формы Windows
Лекция 23
A p p l i c a t i o n . E n a b l e V i s u a l S t y l e s ( ) ; // Разрешает использовать для
элементов управления визуальные стили. Метод должен быть вызван
до добавления в форму элементов управления
// Метод введен дл .NET Framework v e r s i o n 2.0.:
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
// Создание формы
}
}
}
Файл Forms.Designer.cs содержит код метода InitializeComponent, в
котором к окну ф о р м ы добавляются все элементы управления и происхо
дит настройка их свойств. Также в д а н н ы й файл помещается код объявле
н и я элементов управления, размещаемых в форме:
namespace D_1
{ p a r t i a l c l a s s Form1
{
p r i v a t e System.ComponentModel.IContainer
components = n u l l ;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true i f managed resources should be
disposed; otherwise,
false.</param>
protected o v e r r i d e v o i d D i s p o s e ( b o o l d i s p o s i n g )
{
i f ( d i s p o s i n g && (components != n u l l ) )
{ components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method f o r Designer support - do not modify
/// the contents of t h i s method w i t h the code e d i t o r .
/// </summary>
private void InitializeComponent()
{
t h i s . b u t t o n 1 = new System.Windows.Forms.Button();
241
Курс
Введение в программирование
this.textBox1
= new System.Windows.Forms.TextBox();
this.SuspendLayout();
// Элемент управления button1
this.button1.Location
=
new System.Drawing.Point(188, 27);
this.button1.Name = "button1";
t h i s . b u t t o n 1 . S i z e = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 0;
this.button1.Text
= "button1";
this.button1.UseVisualStyleBackColor
= true;
t h i s . b u t t o n 1 . C l i c k +=
new
System.EventHandler(this.button1_Click);
// Элемент управлени
this.textBox1.Location
textBox1
=
new System.Drawing.Point(42, 30);
this.textBox1.Name =
"textBox1";
this.textBox1.Size =
new System.Drawing.Size(100, 20);
this.textBox1.TabIndex = 1;
// Окно формы Form1
this.AutoScaleDimensions =
// Определ ет размер
// окна как ширина и высота ( тип f l o a t )
new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode =
System.Windows.Forms.AutoScaleMode.Font;
t h i s . C l i e n t S i z e = new System.Drawing.Size(292, 266);
this.Controls.Add(this.textBox1);
this.Controls.Add(this.button1);
this.Name = "Form1";
t h i s . T e x t = "Form1";
this.ResumeLayout(false);
this.PerformLayout();
// Заставл ет элемент
// управления выполнить для всех дочерних
// элементов компановку в соответствии
// с их свойствами
}
#endregion
// Объявление переменных
p r i v a t e System.Windows.Forms.Button button1;
242
Библиотека классов .NET Framework среды проектирования
VIsual Studio .NET. Формы Windows
Лекция 23
p r i v a t e System.Windows.Forms.TextBox textBox1;
}
}
Файл Forms.cs содержит описание всех добавляемых пользователем
методов обработки событий ( переход между о к н о м кода и о к н о м дизай
нера для ф о р м ы может быть выполнен вызовом команды контекстного
м е н ю View Code или View Designer).
Для окна ф о р м ы с двумя элементами управления — командная к н о п
ка и поле ввода, и методом обработки события Click файл Forms.cs может
содержать следующий код:
using System;
using System.Collections.Gener
ic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace D_1
{ p u b l i c p a r t i a l c l a s s Form1
: Form
{
p u b l i c Form1()
// Конструктор
{ InitializeComponent();
// Метод определен
//в файле Forms.Designer.cs
}
p r i v a t e v o i d b u t t o n 1 _ C l i c k ( o b j e c t sender,EventArgs e)
{ this.textBox1.Text
= "123456789";
}
}
}
Класс Form
Класс Systems. Windows. Fo rms. Fo rm используется для создания окна формы.
Ф о р м ы позволяют отображать различные т и п ы окон.
• SDI-формы — ф о р м ы , ф у н к ц и о н и р у ю щ и е к а к с а м о с т о я т е л ь н о е
окно.
• MDI-формы — ф о р м ы , к о т о р ы е могут с о д е р ж а т ь д о ч е р н и е ф о р м ы
( с в о й с т в о р о д и т е л ь с к о г о о к н а IsMdiContainer д о л ж н о б ы т ь р а в н о
True. Н а п р и м е р : t h i s . I s M d i C o n t a i n e r = t r u e ; ; с в о й с т в о д о ч е р н е
го о к н а MdiParent д о л ж н о у к а з ы в а т ь н а р о д и т е л ь с к о е о к н о ) ;
243
Курс
Введение в программирование
• формы — диалоги — ф о р м ы , используемые для размещения элементов
управления.
Для создания M D I - п р и л о ж е н и я м о ж н о в пустой проект добавить
н о в ы й элемент M D I Parent.
Для создания формы, идентичной существующей, в проект
следует д о б а в и т ь э л е м е н т Inherited Form и у к а з а т ь к л а с с к о п и р у е м о й
формы.
Создание
новой
формы
Для создания и отображения новой ф о р м ы следует вызвать конст
руктор ф о р м ы и затем вызвать метод Show. П р и этом, если создаваемая
ф о р м а является дочерней, то следует установить значение свойства
MdiParent.
Например:
// Создание нового экземпляра дочерней формы
Form childForm
= new Form();
// Делаем форму дочерней
// для MDI-формы
// до ее отображения
childForm.MdiParent = t h i s ;
childForm.Text
= "Window " + childFormNumber++;
childForm.Show();
// Отображаем дочернюю форму
Закрытие
формы
Закрытие ф о р м ы выполняется вызовом метода Close. Для того, ч т о
бы закрыть все дочерние ф о р м ы в M D I - п р и л о ж е н и и , следует использо¬
вать свойство MdiChildren, содержащее массив дочерних форм.
Например:
private void
CloseAllToolStripMenuItem_Click(
o b j e c t sender,
EventArgs e)
{ foreach
(Form childForm
{
i n MdiChildren)
childForm.Close();
}
}
Класс Form предоставляет большой набор свойств, включая следу¬
ющие:
244
Библиотека классов .NET Framework среды проектирования
VIsual Studio .NET. Формы Windows
Лекция 23
AutoScale
true
Border.Style
FormBorder. Граница окна позволяет масштабирование
Style.Sizable окна
ControlBox
true
StartPosition
Окно и элементы управления масштабируются
автоматически в зависимости от размера
шрифта
О к н о содержит кнопку системного меню
и к н о п к и управления (в верхнем правом
углу). К н о п к и управления показываются,
если свойства MaximizeBox и MinimizeBox
установлены в true
Возможны следующие значения:
Manual; CenterScreen;
WindowsDefaultLocation;
WindowsDefaultBounds; CenterParent
WindowState
Возможны следующие значения:
Normal; Minimized; Maximized
MainMenuStrip
Указывает на линейку меню
IsMdiContainer
Определяет, допускаются ли дочерние окна
IsMdiChild
Определяет, является ли форма
дочерним о к н о м
MdiChildren
Массив форм, содержащий дочерние формы
MdiParent
Ссылка на родительскую M D I - ф о р м у
Controls
Коллекция дочерних элементов управления
Text
Заголовок окна
OwnerForms
Массив форм, принадлежащих данной форме
Owner
Владелец ф о р м ы
Класс Fo rm предоставляет большой набор методов, включая следую¬
щие:
•
•
•
•
•
•
ActiveForm — возвращает активную форму.
Act i vate — активизирует указанную форму.
Close — закрывает форму.
Show — показывает форму.
ShowDialog — показывает форму в виде модального диалога.
Hide — прячет форму.
Для ф о р м ы возможны следующие события:
• C l i c k — щелчок м ы ш ь ю на форме.
• Closing — закрытие ф о р м ы .
245
Курс
Введение в программирование
• Closed — ф о р м а закрыта.
• Load — первоначальное отображение ф о р м ы .
•
•
•
•
A c t i v a t e d — активация ф о р м ы .
D e a c t i v a t e — деактивация ф о р м ы .
GotFocus — получение фокуса ф о р м о й .
LostFocus — потеря ф о р м о й фокуса.
• M d i C h i l d A c t i v a t e — активировано дочернее о к н о для M D I - ф о р м ы .
• MouseEnter — курсор м ы ш и п о м е щ е н над формой.
• MouseLeave — курсор м ы ш и покинул форму.
Дочерние окна в M D I - п р и л о ж е н и и могут быть упорядочены вызо¬
вом метода LayoutMdi.
Например:
// Упорядочивание по горизонтали
t h i s . L a y o u t M d i ( MdiLayout.TileHor i z o n t a l );
// Упор дочивание по вертикали
t h i s . L a y o u t M d i ( M d i L a y o u t . T i l e V e r t i c a l );
// Расположение каскадом
t h i s . L a y o u t M d i ( MdiLayout.Cascade );
Применение стандартных диалогов
Для открытия и закрытия файла, для выбора рисунка или п и к т о
граммы, для определения цвета библиотека . N E T Framework предостав
ляет набор классов стандартных диалогов.
Для использования стандартного диалога сначала требуется создать
переменную типа данного диалога, а затем вызвать метод ShowDialog. Е с
ли в стандартном диалоге было выбрано значение (имя файла, цвет), то
метод ShowDialog возвращает значение true.
Например:
// Вызов стандартного диалога Open
O p e n F i l e D i a l o g o p e n F i l e D i a l o g = new O p e n F i l e D i a l o g ( ) ;
openFileDialog.InitialDirectory =
Environment.GetFolderPath(
Environment.SpecialFolder.Personal);
o p e n F i l e D i a l o g . F i l t e r = "Text F i l e s ( * . t x t ) | * . t x t |
A l l Files (*.*)|*.*";
// Стандартные диалоги отображаютс методом ShowDialog
i f ( o p e n F i l e D i a l o g . S h o w D i a l o g ( t h i s ) ==
DialogResult.OK)
246
Лекция 23
Библиотека классов .NET Framework среды проектирования
VIsual Studio .NET. Формы Windows
// Свойство FileName содержит им выбранного файла
{ s t r i n g FileName = openFileDialog.FileName; }
// Вызов стандартного диалога SaveAs
S a v e F i l e D i a l o g s a v e F i l e D i a l o g = new S a v e F i l e D i a l o g ( ) ;
saveFileDialog.InitialDirectory =
Environment.GetFolderPath(
Environment.SpecialFolder.Personal);
s a v e F i l e D i a l o g . F i l t e r = "Text F i l e s ( * . t x t ) | * . t x t |
A l l Files (*.*)|*.*";
i f ( s a v e F i l e D i a l o g . S h o w D i a l o g ( t h i s ) ==
DialogResult.OK)
{ s t r i n g FileName = s a v e F i l e D i a l o g . F i l e N a m e ; }
Работа с м е н ю
Элемент управления MenuStrip (линейка меню) представляет собой
контейнер для м е н ю , размещаемый в форме. Объект ToolStripMenuItem
может быть добавлен в MenuStrip. Объект ToolStripMenuItemthat является
отдельным элементом м е н ю , который может быть самостоятельной к о
мандой или родительским меню для других элементов подменю.
MenuStrip служит контейнером для объектов следующих классов:
• ToolStripMenuItem,
• ToolStripComboBox,
• ToolStripSeparator,
• ToolStripTextBox.
Класс MenuStrip заменяет и расширяет класс MainMenu предыдущих
версий (класс Main-Menu оставлен для обратной совместимости и дальней
шего использования).
Свойство окна ф о р м ы MainMenuStrip определяет линейку меню для
данного окна.
Например:
// Создание объекта MenuStr i p с новым окном подменю
MenuStrip ms = new MenuStr i p ( ) ;
// Создание подменю
ToolStripMenuItem windowMenu =
new ToolSt ripMenuItem("Window");
ToolStripMenuItem windowNewMenu =
new ToolStripMenuItem("New",
null,
// Обработчик данной команды:
247
Курс
Введение в программирование
new EventHandler(windowNewMenu_Click));
// Список элементов меню
windowMenu.DropDownItems.Add(windowNewMenu);
((ToolStripDropDownMenu)
(windowMenu.DropDown)).ShowImageMargin = f a l s e ;
((ToolStripDropDownMenu)
(windowMenu.DropDown)).ShowCheckMargin = t r u e ;
// Указывает, что T o o l S t r ipMenuItem будет отображать
// список дочерних форм
ms.MdiWindowListItem = windowMenu;
// Добавление окна ToolStripMenuItem к линейке меню
ms.Items.Add(windowMenu);
// Встраивание линейки меню в верх формы.
ms.Dock = DockStyle.Top;
// Свойство Form.MainMenuStr i p определ ет линейку меню
t h i s . M a i n M e n u S t r i p = ms;
Д л я д о б а в л е н и я к ф о р м е л и н е й к и м е н ю следует на п а н е л и инстру
ментов выбрать элемент управления MenuStrip (или MainMenu в предыду
щ и х версиях).
248
Лекция 24
Библиотека классов VCL среды проектирования Delphi
Л е к ц и я 2 4 . Б и б л и о т е к а к л а с с о в VCL с р е д ы
п р о е к т и р о в а н и я Delphi
К о м п о н е н т ы Delphi
Объекты
Объект Delphi представляет собой набор свойств и методов, включа¬
ю щ и х также обработчики событий. Свойства, называемые иногда атрибу¬
тами, являются д а н н ы м и , содержащимися в объекте. Методы описывают
действия, реализованные для данного объекта.
Все объекты имеют общего предка — класс TObject.
Компоненты
Компонент Delphi — это особый вид объектов — визуальный объект
(визуальный для проектирования, а не для отображения пользователя).
Создавать и редактировать такой объект м о ж н о как программным путем,
так и на этапе проектирования.
П р и в ы п о л н е н и и программы к о м п о н е н т ы делятся на визуальные,
которые видит пользователь, и невизуальные, для которых нет возможно
сти их отображения, но доступ к свойствам которых разрешен.
Все к о м п о н е н т ы имеют общего предка — класс TComponent.
Delphi предоставляет ш и р о к и й набор компонентов, называемый
иногда VCL-библиотекой. Все к о м п о н е н т ы Delphi могут быть доступны
через палитру компонентов.
В настоящее время в Borland Developer Studio входит Delphi 2006 for
Win32 (использует библиотеку V C L ) и Delphi 2006 for Microsoft . N E T (ис
пользует библиотеку Framework 1.1).
Часть компонентов являются элементами управления. В основном
это элементы управления Windows. Доступ к элементам управления воз
можен не только на этапе проектирования, но и во время выполнения
приложения.
Элементы управления м о ж н о подразделить на оконные и неоконные.
О к о н н ы е элементы могут получать фокус и имеют дескриптор окна.
П р е д к о м всех о к о н н ы х элементов управления является абстрактный
класс TWinControl. Предком неоконных элементов управления является
абстрактный класс T G r a p h i c C o n t r o l .
П р и добавлении в форму любого компонента из палитры компонен¬
тов Delphi автоматически формирует программный код для создания объ249
Курс
Введение в программирование
екта (переменной) данного типа. Переменная добавляется к а к член клас¬
са д а н н о й формы.
Б и б л и о т е к а VCL
Иерархия классов
Классы библиотеки V C L используют механизм простого наследова
ния: один класс может иметь только одного предка. К о р н е м иерархии
классов является класс TObject. Любой класс VCL-библиотеки наследует
ся от класса TObject.
Н а рис. 1 представлена корневая часть дерева иерархии классов V C L библиотеки.
TObject
Рис. 1. Иерархия классов VCL-библиотеки
Класс TObject
К л а с с TObject и н к а п с у л и р у е т о б щ и е ч е р т ы п о в е д е н и я всех о б ъ е к
тов V C L - б и б л и о т е к и . Е с л и п р и с о з д а н и и н о в о г о объекта н е у к а з а н ба
з о в ы й к л а с с , то D e l p h i а в т о м а т и ч е с к и использует к а к п р е д к а к л а с с
TObject.
250
Лекция 24
Библиотека классов VCL среды проектирования Delphi
Объявление нового класса выполняется в секции type. Если после сло
ва c l a s s в скобках не указано никакого наследуемого класса, то по умолча
нию предполагается, что создаваемый класс наследуем от класса TObject.
Например:
type TMyClass = c l a s s
// Эти два объявления
type TMyClass = c l a s s ( T O b j e c t )
//являются эквивалентными
Класс TComponent
TComponent является предком всех компонентов VCL-библиотеки.
Все потомки данного класса могут быть расположены в палитре
компонентов.
Класс TComponent позволяет определять родительский элемент управ
л е н и я и владельца компонента.
Родительским элементом управления называется тот, в который непо¬
средственно п о м е щ е н д а н н ы й компонент.
Владельцем всех компонентов, расположенных в форме, является са
ма форма. Владельцем всех ф о р м является приложение.
Если компонент расположен н е непосредственно в форме, а, напри¬
мер, в компоненте типа TPanel, то владелец и родительский элемент уп
равления у него будут различны.
Класс предоставляет большой набор свойств, включая следующие:
• ComObject — определяет ссылку н а и н т е р ф е й с , наследуемый от
IUnknown и реализованный компонентом. Используется только для
компонентов, поддерживающих С О М - и н т е р ф е й с .
• ComponentCount — указывает количество компонентов, принадлежа¬
щих данному компоненту.
• ComponentIndex — указывает индекс компонента в массиве Components
владельца данного компонента. П е р в ы й компонент в списке имеет
индекс 0.
• Components — список всех компонентов, принадлежащих данному
компоненту. Используется для ссылки на компонент п о его индексу
или для последовательного доступа к о всем компонентам, принадле¬
ж а щ и х данному компоненту.
• Name — указывает и м я компонента, используемое в коде программы
для доступа к его свойствам и методам. П р и создании компонента
Delphi автоматически назначает ему и м я на основе имени класса
компонента.
• Owner — указывает компонент, владеющий д а н н ы м компонентом.
К о м п о н е н т всегда удаляется (освобождается память) при удалении
его владельца.
251
Курс
Введение в программирование
Класс TControl
TControl — это базовый класс всех элементов управления (включая и
о к н о ф о р м ы ) . Эти к о м п о н е н т ы могут быть видимы во время выполнения.
Для них определены такие свойства, к а к п о з и ц и я , курсор, всплывающая
подсказка, методы для рисования или перемещения элемента управле
н и я , события для манипуляций с п о м о щ ь ю м ы ш и .
Класс предоставляет большой набор свойств, включая следующие:
• Action — назначает действие (объект a c t i o n ) , ассоциируемый с д а н
н ы м элементом управления.
• AutoSize — определяет, будет ли элемент управления автоматически
изменять свой размер при изменении его содержимого.
• TCaption — определяет строку, отображаемую как заголовок окна или
метку. Символ & в заголовке указывает, что следующий за н и м с и м
вол будет отображаться подчеркнутым. Такой символ определяет
клавишу-акселератор. П р и одновременном нажатии этой к л а в и ш и и
клавиши A l t происходит перемещение фокуса ввода на д а н н ы й эле
мент управления. Для того, чтобы показать в заголовке сам символ
амперсанда, следует ввести два символа &&.
• Color — позволяет определять или изменять ф о н о в ы й цвет элемента
управления. Если значение свойства ParentColor равно True, то при
изменении ф о н а родительского элемента управления происходит и
автоматическое изменение ф о н а дочернего элемента управления.
• Enabled — определяет, доступен ли элемент управления.
• Font — определяет атрибуты текста, такие, как шрифт, начертание,
размер, цвет и т.п.
• Height и Width — определяют вертикальный и горизонтальный раз
мер элемента управления в пикселях.
• HelpType — определяет, каким образом для элемента управления бу¬
дет специфицирована тема файла справки. Если значение свойства
равно htContext, то I D справки содержится в свойстве HelpContext.
Если значение свойства равно htKeyword, то тему справки определя
ет свойство HelpKeyword.
• HelpContext — определяет числовой I D темы справки, отображаемой
как контекстно-зависимая справка.
• HelpKeyword — определяет тему в файле справки.
• Hint - содержит подсказку, отображаемую при расположении и за
держании указателя м ы ш и над элементом управления. Подсказка
отображается только, если значение свойства ShowHint установлено
равным True.
• Left — определяет горизонтальную координату элемента управления
относительно его родительского элемента.
252
Лекция 24
Библиотека классов VCL среды проектирования Delphi
• Parent — указывает родительский элемент управления.
• ParentColor и ParentFont — если это свойства равны true, то исполь
зуются цвет и ш р и ф т родительского элемента управления.
• PopupMenu — определяет всплывающее меню (контекстное меню), ас
с о ц и и р у е м о е с д а н н ы м э л е м е н т о м у п р а в л е н и я . Е с л и свойство
AutoPopup объекта типа TPopupMenu равно True, то м е н ю будет отобра
жаться автоматически. Если это свойство равно False, то для отобра
ж е н и я в с п л ы в а ю щ е г о м е н ю следует в о б р а б о т ч и к е с о б ы т и я
OnContextPopup вызвать метод Popup.
• ShowHint — определяет, будет ли для элемента управления отобра
жаться о к н о всплывающей подсказки.
• Text — содержит строку текста, располагаемую в элементе управления.
• V i s i b l e — определяет, является ли компонент видимым.
Класс предоставляет большой набор методов, включая следующие:
• C l i c k — инициирует событие OnClick.
• Create — создает экземпляр класса TControl и выполняет инициали¬
зацию его свойств.
• D b l C l i c k — инициирует событие OnDblClic.
• Hide — скрывает элемент управления.
• Refresh — сразу перерисовывает на экране элемент управления, в ы
зывая метод Repaint.
• Show — делает элемент управления видимым, одновременно устанав
ливая значение его свойства V i s i b l e равным True.
Класс TWinControl
Класс TWinControl является базовым классом всех о к о н н ы х элемен
тов управления.
Класс предоставляет большой набор свойств, включая следующие:
• Cont rolCount — указывает количество дочерних элементов управления.
• C o n t r o l s — содержит список всех дочерних элементов управления.
• TabOrder — указывает номер элемента управления в табулированном
порядке родительского элемента управления.
Класс TApplication
Класс T A p p l i c a t i o n инкапсулирует объект «Windows-приложение».
Посредством этого класса определяется интерфейс между разработчиком
и средой Windows.
В каждом приложении Delphi всегда автоматически создается один
объект Application как экземпляр класса приложения. Для большинства
приложений этот объект является экземпляром класса T A p p l i c a t i o n .
253
Курс
Введение в программирование
К о м п о н е н т T A p p l i c a t i o n не отображается в палитре компонентов и
не имеет публикуемых свойств. Для того чтобы иметь возможность пере
хватывать события для приложения, используя среду разработки I D E ,
м о ж н о добавить в любую форму проекта компонент T A p p l i c a t i o n E v e n t s .
Класс предоставляет большой набор свойств, включая следующие:
• H e l p F i l e — определяет имя файла справки.
• Icon — определяет пиктограмму, отображаемую в строке вместе с
именем приложения.
• MainForm — определяет главную форму приложения. Она действует
как главное о к н о приложения. П р и закрытии этой ф о р м ы заверша
ется и работа приложения.
• ShowMainForm — если значение свойства равно True (по умолчанию), то
главное о к н о приложения показывается автоматически при запуске
приложения. Чтобы при запуске приложения главное окно приложе
н и я было скрыто, следует в главном файле проекта до выполнения
метода Application.Run установить значение данного свойства рав
н ы м False и одновременно для формы, определенной как главное ок
но приложения, установить значение свойства V i s i b l e равным False.
• T i t l e — определяет заголовок приложения.
Класс TScreen
Каждое приложение Delphi имеет глобальную переменную Screen
типа TScreen. Эта переменная определена как var Screen: TScreen;.
К о м п о н е н т TScreen, так ж е как и компонент T A p p l i c a t i o n , недосту
пен из инспектора объектов. Этот компонент предназначен для обеспече
н и я доступа к устройству вывода — экрану. Его свойства содержат инфор¬
м а ц и ю об используемом разрешении монитора, курсорах и шрифтах, до¬
ступных для приложения, списке ф о р м приложения и активной форме.
Класс TForm
TFo rm является базовым классом для создания окна ф о р м ы .
П о умолчанию каждая новая создаваемая форма реализуется как п о
томок класса TForm. Форма может быть:
• главным о к н о м приложения;
• диалоговым о к н о м ;
• дочерним о к н о м M D I - о к н а .
Класс предоставляет большой набор свойств, включая следующие:
• A c t i v e — определяет, является ли форма активной.
• A c t i v e C o n t r o l — определяет элемент управления ф о р м ы , и м е ю щ и й
фокус ввода.
254
Лекция 24
Библиотека классов VCL среды проектирования Delphi
Например:
i f A c t i v e C o n t r o l <> n i l then
A c t i v e C o n t r o l . L e f t := A c t i v e C o n t r o l . L e f t + 1;
end;
• A c t i v e M D I C h i l d — определяет активное дочернее о к н о M D I - п р и л о жения;
• B o r d e r S t y l e — определяет в н е ш н и й вид и поведение р а м к и окна
формы;
• FormStyle — определяет стиль ф о р м ы , который указывается одним
из следующих значений:
• fsNormal — форма определена как простая S D I - ф о р м а и не я в л я
ется н и дочерним, н и родительским M D I - о к н о м ;
• fsMDIChild — форма является дочерним M D I - о к н о м .
• fsMDIForm — форма является родительским M D I - о к н о м .
• fsStayOnTop — для ф о р м ы определено поведение «всегда сверху»
(она остается сверху всех других ф о р м проекта, для которых не ус
тановлен стиль fsStayOnTop).
• H e l p F i l e — указывает и м я файла, используемого для отображения
справки.
• Icon — определяет пиктограмму, отображаемую в заголовке окна формы.
• MDIChildCount — определяет количество открытых дочерних M D I форм.
• MDIChildren — содержит с п и с о к всех дочерних M D I - ф о р м .
Например:
{Закрытие всех дочерних MDI-форм}
var
I n d e x l : Integer;
begin
with MyForm1 do
f o r I := MDIChildCount-1 downto 0 do
MDIChildren[Index1].Close;
end;
• Menu — определяет главное меню.
• Parent — определяет родительское окно. Если форма не имеет роди
теля, то значение свойства Parent равно n i l .
• P o s i t i o n — указывает размер и п о з и ц и ю , используемые для первона
чального отображения формы.
• WindowState — определяет, в каком виде форма появляется на экране:
свернутой, п о л н о э к р а н н о й или в нормальном представлении.
255
Курс
Введение в программирование
Класс ф о р м ы предоставляет большой набор методов, включая сле¬
дующие:
• Cascade — упорядочивает все дочерние M D I - ф о р м ы , располагая их
каскадом.
• Next — делает активной следующую дочернюю форму (в той после¬
довательности, к а к о н и были открыты).
• Previous — делает активной предыдущую дочернюю форму.
• T i l e — упорядочивает все дочерние M D I - ф о р м ы таким образом,
чтобы о н и все имели одинаковый размер и умещались одновремен¬
н о в клиентской области родительского окна.
Например:
{Обработчик события для команды меню Windows | T i l e }
procedure TForm1.TileFormsClick(Sender: TObject);
begin
t h i s . T i l e M o d e := t b V e r t i c a l ;
this.Tile;
end;
Класс ф о р м ы является контейнером для всех компонентов, разме
щаемых на форме. Д л я доступа к свойствам ф о р м ы и л и именам компо¬
нентов м о ж н о использовать ключевое слово this. Если перед именем
свойства отсутствует какой-либо идентификатор, то по умолчанию пред¬
полагается, что это свойство формы.
Класс TMainMenu
Класс TMainMenu инкапсулирует поведение линейки меню (menu bar) и
соответствующих ниспадающих меню (drop-down menus) для окна ф о р м ы .
Этот класс определяет свойства и методы, позволяющие соединять
н и с п а д а ю щ и е м е н ю главного м е н ю с главными меню других ф о р м и по¬
могающие взаимодействовать с меню для OLE-объектов.
Процесс создания меню формы очень прост. Он состоит из трех этапов:
1.
добавления в форму компонента класса TMainMenu;
2.
выполнения на нем двойного щелчка м ы ш ь ю и ввода в открытое да¬
лее о к н о заголовков всех пунктов л и н е й к и меню и пунктов ниспада¬
ющих м е н ю ;
3.
определения кода обработчиков событий для каждого пункта меню.
Если требуется синхронизировать код, в ы п о л н я е м ы й для пункта м е
ню, с кодом, в ы п о л н я е м ы м для к н о п к и на панели управления, то созда
ется объект «действие типа Taction», который указывается и для пункта
м е н ю , и для к н о п к и .
256
Лекция 24
Библиотека классов VCL среды проектирования Delphi
Класс предоставляет набор свойств, включая следующие:
• AutoMerge — определяет возможность с л и я н и я меню. К а к и м образом
меню будут объединяться, зависит от значения свойства GroupIndex
каждого отдельного пункта м е н ю ;
• Handle — обеспечивает доступ к дескриптору меню. Это свойство ис
пользуется для функций Windows A P I , требующих дескриптора меню.
Класс TMenuItem
Класс TMenuItem реализует поведение пунктов меню. Контейнером для
объектов типа TMenuItem может быть компонент типа TMainMenu (линейка
главного меню) или компонент типа TPopupMenu (контекстное меню).
П р и создании меню на этапе проектирования редактор меню Menu
Designer автоматически создает объекты типа TMenuItem для каждой ко¬
манды меню.
Класс предоставляет набор свойств, включая следующие:
• A c t i o n — определяет объект действие (Action), ассоциируемый с
пунктом меню. П о умолчанию для каждого пункта м е н ю стандарт
н ы м событием считается OnClick и обработчиком события является
процедура, и м я которой автоматически формируется из и м е н и фор¬
м ы и и м е н и объекта «пункт меню», указанных через точку (напри¬
мер, TForml. item12Click). Объект «действие» позволяет определить
одну процедуру обработки события, которую далее м о ж н о будет
многократно использовать для различных объектов при обработке
событий.
• AutoHotkeys — определяет, будут ли клавиши-акселераторы для эле
ментов подменю устанавливаться автоматически.
• Bitmap — определяет изображение, отображаемое слева от заголовка
меню.
• Break — определяет, будет ли пункт меню располагаться в новом
столбце меню.
• Caption — определяет текст пункта меню. Если перед буквой в заго
ловке пункта меню стоит символ &, то данная буква называется кла¬
вишей-акселератором, а выбор пункта меню может быть выполнен
одновременным нажатием A l t и клавиши-акселератора.
• Checked — определяет, будет ли маркер переключателя появляться в
пункте меню слева от заголовка.
• D e f a u l t — определяет, является ли д а н н ы й пункт меню пунктом, в ы
п о л н я е м ы м по умолчанию при д в о й н о м щелчке м ы ш ь ю на роди
тельском подменю. Пункт меню, в ы п о л н я е м ы й по умолчанию, от
мечается полужирным начертанием.
• Enabled — определяет, доступен ли пункт меню.
257
Курс
Введение в программирование
• GroupIndex — указывает логическую группу, к которой принадлежит
пункт м е н ю (группы используются для управления слиянием пунк¬
тов меню).
П о умолчанию все пункты л и н е й к и м е н ю имеют одинаковое значе¬
н и е GroupIndex. П р и использовании этого свойства для с л и я н и я меню
следует установить значения каждого пункта л и н е й к и м е н ю равным пре¬
дыдущему или большим.
Если значение свойства GroupIndex добавляемого меню совпадает со
значением свойства GroupIndex пункта главного м е н ю , то последний заме
няется на добавляемый. Если несколько пунктов меню главного окна
имеет одинаковое значение свойства G roupIndex, то и заменены о н и могут
быть только несколькими пунктами добавляемого меню: первый пункт с
одинаковым значением заменяется на первый добавляемый пункт с оди
наковым значением, второй — на второй и т.д.
Если значение свойства GroupIndex добавляемого пункта л и н е й к и
меню лежит между значениями свойства GroupIndex пунктов л и н е й к и ме
н ю главного окна, то добавляемый пункт вставляется между н и м и .
• HelpContext — указывает I D контекста справки, отображаемой для
пункта меню.
• Hint — определяет текст всплывающего окна подсказки.
• ImageIndex — определяет индекс изображения, отображаемого для
пункта меню. С п и с о к изображений, указываемых через индекс, со¬
держится в свойстве Images родительского меню: для пунктов меню
верхнего уровня список определяется свойством Images объекта типа
TMenu или TPopupMenu, а для пунктов подменю список определяется
свойством Images родительского объекта меню типа TMenuItem. Если
родительское м е н ю н е содержит списка изображений в свойстве
Images, то для определения отображаемого изображения будет и с
пользовано значение свойства Bitmap пункта меню.
• Items — с п и с о к пунктов меню в подменю.
• MenuIndex — указывает индекс пункта меню в родительском меню.
• Parent — определяет для пункта меню его родительское меню.
• V i s i b l e — определяет, является ли пункт меню видимым.
Класс предоставляет набор методов, включая следующие:
• Add — добавляют в конец списка Items один или несколько пунктов меню.
Например:
var
NewItem: TMenuItem;
i : integer;
begin
// Создание элемента «разделительная линия»:
NewItem := TMenuItem.Create(Self);
258
Лекция 24
Библиотека классов VCL среды проектирования Delphi
NewItem.Caption :=
// Заголовок пункта меню
// Добавление пункта меню к меню Windows:
Windows.Add(NewItem);
// Издадим и добавим пункт меню для каждой формы
for
i := 0 t o Screen.FormCount-1 do
begin
NewItem := TMenuItem.Create(Self);
NewItem.Caption := Screen.Forms[ i].Name;
Windows.Add(NewItem);
end;
end;
• C l e a r — удаляет все пункты меню, указанные в списке свойства Items.
• C l i c k — инициирует событие OnClick. Этот метод может быть пере¬
определен разработчиком для того, чтобы запрограммировать собст¬
в е н н ы й ответ н а выбор пользователем пункта меню.
• Create — создает н о в ы й пункт меню.
• Delete — удаляет и з списка свойства Items пункт меню с указанным
индексом.
• IndexOf — возвращает позицию указанного пункта меню в списке Items.
• I n s e r t — вставляет указанный пункт меню в заданную позицию спи¬
ска Items.
Разработчик может создать один о б щ и й объект «действие» и для
пункта меню, и для к н о п к и панели инструментов. Д л я определения д е й
ствия на этапе проектирования следует:
1.
добавить в форму объект типа Taction L i s t ;
2.
вызвать редактор объекта «действие», выполнив н а н е м двойной
щелчок м ы ш ь ю ;
3.
д о б а в и т ь в о т к р ы в ш е м с я р е д а к т о р е о б ъ е к т ы «действие (типа
TAction)»;
4.
по двойному щелчку на и м е н и любого объекта «действие» отобража
ется редактор кода с автоматически добавленным обработчиком с о
бытия для данного действия. Например:
procedure TForm1.Action1Execute(Sender: TObject);
begin
end;
5.
Внутри блока begin end следует ввести код обработчика события;
в завершение нужно определить для объекта «пункт меню» значение
свойства A c t i o n , выбрав его и з с п и с к а д е й с т в и й объекта типа
TActionList.
259
Курс
Введение в программирование
Класс TPopupMenu
Класс TPopupMenu инкапсулирует поведение контекстных меню, так
ж е называемых всплывающими или popup-меню.
Он предназначен для создания меню, отображаемых при щелчке
пользователя правой к н о п к о й м ы ш и на элементе управления. Ч т о б ы кон¬
текстное меню поставить в соответствие конкретному элементу управле¬
н и я , следует установить значение свойства PopupMenu элемента управле
н и я равным и м е н и объекта TPopupMenu. Для этого в инспекторе объектов
следует выбрать значение свойства PopupMenu из автоматически предлага¬
емого списка объектов типа TPopupMenu.
Базовым классом для TPopupMenu является класс TMenu.
Следующий пример иллюстрирует отображение контекстного меню
в указанной точке экрана по щелчку м ы ш и :
procedure Form1.FormCreate(Sender: TObject);
begin
PopupMenu1.AutoPopup := False;
end;
procedure Form1.FormMouseDown(Sender: TObject;
Button: TMouseButton;
Shift: TShiftState;
X, Y: I n t e g e r ) ;
begin
PopupMenu1.Popup(X, Y);
end;
260
Лекция 25
Библиотека классов VCL среды проектирования Delphi.
Приложения и диалоги
Л е к ц и я 2 5 . Б и б л и о т е к а к л а с с о в VCL с р е д ы
п р о е к т и р о в а н и я Delphi. П р и л о ж е н и я и д и а л о г и
Создание приложений
Проекты
Л ю б о е п р и л о ж е н и е в среде п р о е к т и р о в а н и я Delphi создается к а к
н е к о т о р ы й проект. В зависимости от т и п а п р и л о ж е н и я , в проект входит
р а з л и ч н ы й набор ф а й л о в проекта. Н о в л ю б о м случае составной частью
проекта я в л я е т с я ф а й л проекта с р а с ш и р е н и е м D P R . К а ж д а я ф о р м а в
проекте представляется двумя ф а й л а м и : ф а й л модуля с р а с ш и р е н и е м
PAS и ф а й л о п и с а н и я ф о р м ы с р а с ш и р е н и е м D F M . Ф а й л о п и с а н и я
ф о р м ы н е может редактироваться непосредственно, д а н н ы е в него з а н о
сятся средой п р о е к т и р о в а н и я . В к а ж д ы й проект входит один г л а в н ы й
ф а й л п р и л о ж е н и я . Д л я диалоговых п р и л о ж е н и й этот ф а й л начинается с
ключевого слова program. Ф а й л модуля д л я ф о р м ы начинается к л ю ч е
в ы м словом unit.
Для создания нового приложения среда проектирования Delphi пре
доставляет большой набор шаблонов приложений, включающий п р и л о
жение-диалог, S D I - п р и л о ж е н и е и M D I - п р и л о ж е н и е .
Основное отличие автоматически формируемого макета приложе¬
н и я на базе шаблона M D I - п р и л о ж е н и я от п р и м е н е н и я шаблона S D I приложения заключается в поддержке одновременной работы с несколь
к и м и документами. К а ж д ы й н о в ы й документ открывается в создаваемом
дочернем окне.
Дополнительно шаблон M D I - п р и л о ж е н и я содержит к н о п к и для и з
менения расположения о к о н , а в м е н ю Windows добавляются имена всех
открытых документов.
Создание MDI-приложения
П р и использовании шаблона M D I - п р и л о ж е н и я создается проект,
состоящий из трех модулей (main.pas, childwin.pas, about.pas) и главного
файла приложения.
Для главной ф о р м ы приложения (main.pas) свойство Fo rmStyle будет
установлено равным fsMDIForm, а для дочерней ф о р м ы (childwin.pas) —
fsMDIChild.
Класс главной ф о р м ы приложения определяется следующим
кодом:
261
Курс
Введение в программирование
type
TMainForm = class(TForm)
MainMenu1: TMainMenu;
{Компонент главного меню}
F i l e 1 : TMenuItem;
{ Компоненты элементов меню}
FileNewItem: TMenuItem;
FileOpenItem: TMenuItem;
F i l e C l o s e I t e m : TMenuItem;
Window1: TMenuItem;
Help1: TMenuItem;
N1: TMenuItem;
F i l e E x i t I t e m : TMenuItem;
WindowCascadeItem: TMenuItem;
WindowTileItem: TMenuItem;
WindowArrangeItem: TMenuItem;
HelpAboutItem: TMenuItem;
OpenDialog: TOpenDialog;
FileSaveItem: TMenuItem;
FileSaveAsItem: TMenuItem;
E d i t 1 : TMenuItem;
CutItem: TMenuItem;
CopyItem: TMenuItem;
PasteItem: TMenuItem;
WindowMinimizeItem: TMenuItem;
StatusBar: TStatusBar;
{Компонент строки состояния}
ActionList1: TActionList;
{Компонент для определения
списка именованных действий}
E d i t C u t 1 : TEditCut;
{ Компонент дл копировани
в буфер обмена}
EditCopy1: TEditCopy;
EditPaste1: TEditPaste;
FileNew1: TAction;
{ Компонент именованного действи }
F i l e S a v e 1 : TAction; F i l e E x i t 1 : TAction;
FileOpen1: TAction; F i l e S a v e A s 1 : TAction;
WindowCascade1: TWindowCascade;
WindowTileHor i z o n t a l 1 : TWindowTileHorizontal;
WindowArrangeAll1: TWindowArrange;
WindowMinimizeAll1: TWindowMinimizeAll;
HelpAbout1: TAction;
F i l e C l o s e 1 : TWindowClose;
WindowTileVertical1: TWindowTileVertical;
WindowTileItem2: TMenuItem;
ToolBar2: TToolBar;
{Панель инструментов}
262
Лекция 25
Библиотека классов VCL среды проектирования Delphi.
Приложения и диалоги
ToolButton1: TToolButton;
{Кнопки панели инструментов}
ToolButton2: TToolButton;
ToolButton3: TToolButton;
ToolButton4: TToolButton;
ToolButton5: TToolButton;
ToolButton6: TToolButton;
ToolButton9: TToolButton;
ToolButton7: TToolButton;
ToolButton8: TToolButton;
ToolButton10: TToolButton;
ToolButton11: TToolButton;
ImageList1: TImageList;
procedure FileNew1Execute(Sender: TObject);
procedure FileOpen1Execute(Sender: TObject);
procedure HelpAbout1Execute(Sender:
TObject);
procedure F i l e E x i t 1 E x e c u t e ( S e n d e r : TObject);
end;
В коде модуля main.pas должно быть указано использование двух
других модулей п р и л о ж е н и я : uses ChildWin, About;.
Процедура создания нового документа или открытия существующе¬
го реализована следующим кодом:
{Создать новый документ}
procedure TMainForm.FileNew1Execute(Sender: TObject);
begin
{Создание дочернего окна с новым именем}
CreateMDIChild('NONAME' + IntToStr(MDIChildCount + 1 ) ) ;
end;
{Открыть документ}
procedure TMainForm.FileOpen1Execute(Sender:
TObject);
begin
i f OpenDialog.Execute then
{Выбор имени документа}
CreateMDIChild(OpenDialog.FileName);
{ Создание окна}
end;
procedure TMainForm.CreateMDIChild(const
Name: s t r i n g ) ;
var
C h i l d : TMDIChild;
begin
{ Класс TMDIChild определен в модуле CHILDWIN.PAS }
C h i l d := T M D I C h i l d . C r e a t e ( A p p l i c a t i o n ) ; { Создание окна}
C h i l d . C a p t i o n := Name;
{ Заголовком окна будет
263
Курс
Введение в программирование
им файла}
i f F i l e E x i s t s ( N a m e ) then
// Дочернее окно содержит поле типа TMemo, в которое
// выполн етс загрузка текстового файла:
Child.Memo1.Lines.LoadFromFile(Name);
end;
Для завершения приложения выполняется следующая процедура:
procedure TMainForm.FileExit1Execute(Sender: TObject);
begin Close; end;
В модуле c h i l d w i n . p a s находитс код дочерней формы:
type
TMDIChild = class(TForm)
Memo1: TMemo;
{ Поле дл отображени текста}
procedure FormClose(Sender: TObject;
var Action: TCloseAction);
end;
implementation
procedure TMDIChild.FormClose(Sender:
TObject;
var Action: TCloseAction);
begin
A c t i o n := caFree; end;
end.
Главная форма приложения описывается следующими свойствами
(полужирным ш р и ф т о м и курсивом выделены свойства, значения кото¬
рых н е могут быть другими):
o b j e c t MainForm: TMainForm
Caption = 'Приложение с MDI-интерфейсом'
FormStyle = fsMDIForm
Menu = MainMenu1
WindowMenu = Window1
o b j e c t S t a t u s B a r : TStatusBar
AutoHint = True
Panels = <>
SimplePanel = True
end
o b j e c t ToolBar2: TToolBar
Images = ImageList1
o b j e c t ToolButton9: TToolButton
A c t i o n = FileNew1
{Именованное действие,
которое будет выполнено при щелчке на кнопке}
end
264
Библиотека классов VCL среды проектирования Delphi.
Приложения и диалоги
Лекция 25
o b j e c t ToolButton1: TToolButton
A c t i o n = FileOpen1
end
{ Кнопки панели инструментов}
end
o b j e c t MainMenu1: TMainMenu
Images = ImageList1
o b j e c t F i l e 1 : TMenuItem
Caption = ' & F i l e '
o b j e c t FileNewItem: TMenuItem
A c t i o n = FileNew1
end
o b j e c t FileOpenItem: TMenuItem
A c t i o n = FileOpen1
end
o b j e c t F i l e C l o s e I t e m : TMenuItem
Action = FileClose1
end
o b j e c t F i l e E x i t I t e m : TMenuItem
Action = F i l e E x i t 1
end
end
object Edit1:
TMenuItem
end
o b j e c t Window1:
TMenuItem
end
end
o b j e c t OpenDialog: TOpenDialog
Filter = ' A l l f i l e s (*.*)|*.*'
end
object A c t i o n L i s t 1 : TActionList
o b j e c t FileNew1: T A c t i o n
Category = ' F i l e '
Caption = '&New'
OnExecute = FileNew1Execute
end
o b j e c t FileOpen1: T A c t i o n
Category = ' F i l e '
265
{ Диалог Open}
Курс
Введение в программирование
Caption = ''&Open'
OnExecute =
= FileOpen1Execute
end
end
end
Дочерняя форма фактически является обычной ф о р м о й , в которую
п о м е щ е н один объект типа TMemo (многострочное поле редактирования).
Она описывается следующими свойствами:
o b j e c t MDIChild: TMDIChild
FormStyle = fsMDIChild
P o s i t i o n = poDefault
V i s i b l e = True
OnClose = FormClose
o b j e c t Memo1: TMemo
WordWrap = False
end
end
П о с л е того к а к м а к е т п р и л о ж е н и я с о з д а н н а базе ш а б л о н а M D I п р и л о ж е н и я , его м о ж н о и з м е н я т ь , д о б а в л я я н о в ы е к о м а н д ы м е н ю и
компоненты типа TAction для реализации именованных действий. В
проект можно добавлять новые ф о р м ы и редактировать уже сущест
вующие.
Создание DLL-библиотеки
DLL-библиотека позволяет объединить в единое целое повторно и с
пользуемый код. Ф у н к ц и и из DLL-библиотеки могут подключаться д и
намически во время в ы п о л н е н и я , в отличие от ф у н к ц и й из пакетов Delphi
линкуемых статически на этапе к о м п и л я ц и и приложения.
Для того чтобы создать DLL-библиотеку, следует использовать ш а б
лон приложения D L L Wizard.
В отличие от обычного модуля, начинающегося с ключевого слова
unit, модуль DLL-библиотеки начинается с ключевого слова l i b r a r y .
Секция uses модуля DLL-библиотеки требует подключения только
двух пакетов: S y s U t i l s и Classes.
Ф у н к ц и и и з DLL-библиотеки могут вызываться к а к и з приложений,
разработанных в Delphi, т а к и из п р и л о ж е н и й , н а п и с а н н ы х н а других
языках программирования, таких к а к C++.
266
Лекция 25
Библиотека классов VCL среды проектирования Delphi.
Приложения и диалоги
Порядок выделения памяти под параметры и освобождения ее раз
личен для разных я з ы к о в программирования. Чтобы н е возникла ошибка
времени в ы п о л н е н и я , объявление ф у н к ц и и в DLL-библиотеке и ее объ
я в л е н и е в приложении должны использовать одинаковый механизм пере¬
дачи параметров.
П р и объявлении процедуры или ф у н к ц и и может быть указан один
из следующих механизмов передачи параметров:
•
•
•
•
•
register,
pascal,
cdecl,
stdcall,
safecall.
Способ передачи параметров указывается через точку с запятой п о
сле описания ф у н к ц и и .
Н а п р и м е р : f u n c t i o n F1 (X, Y, Z: R e a l ) : Real;
stdcall;
Различные способы передачи параметров определяют порядок их
передачи (слева направо и л и справа налево), а также указывают, кто будет
освобождать память стека (вызываемая и л и вызывающая процедура).
Для того чтобы ф у н к ц и ю , описанную в DLL-библиотеке, м о ж н о б ы
ло вызвать из другого приложения, эту ф у н к ц и ю следует экспортировать.
С п и с о к всех экспортируемых ф у н к ц и й указывается в секции exports через
запятую и завершается символом «точка с запятой».
Экспорт ф у н к ц и й может выполняться тремя способами:
• по и м е н и ф у н к ц и и , используемому в DLL-библиотеке;
• по и м е н и ф у н к ц и и , заданному к а к и м я экспорта;
• по присвоенному ф у н к ц и и индексу (указанному в секции exports).
Например:
l i b r a r y Project1;
uses
SysUtils,
Classes;
{$R *.res}
f u n c t i o n F1(X: I n t e g e r ) : Integer; s t d c a l l ;
begin
F1:=X*2;
end;
f u n c t i o n F2(X: I n t e g e r ) : Integer; s t d c a l l ;
begin
F2:=X*X;
end;
exports
F1 ,
{Функция будут доступна по имени F1}
F2 index 2 ;
{Функция будут доступна по индексу 2}
end.
267
Курс
Введение в программирование
DLL-библиотека н е является в ы п о л н я е м ы м модулем, поэтому для
получения dll-файла достаточно произвести к о м п и л я ц и ю проекта.
Статическое и динамическое подключения DLL-библиотеки
DLL-библиотека может подключаться или статически, или д и н а м и
чески. П р и подключении DLL-библиотеки она загружается в память п р и
ложения.
П р и статическом подключении DLL-библиотека загружается один
раз п р и запуске приложения.
Н а всем п р о т я ж е н и и в ы п о л н е н и я п р и л о ж е н и я и м я ф у н к ц и и , и м
п о р т и р у е м о й и з D L L - б и б л и о т е к и , к о т о р а я б ы л а п о д к л ю ч е н а статиче
ски, у к а з ы в а е т н а одну и ту ж е ф у н к ц и ю (точку входа в D L L ) в о д н о й и
той же D L L .
В отличие от статического подключения DLL-библиотеки, выпол
няемого в момент загрузки приложения, динамическое подключение м о
жет быть выполнено в любой точке выполнения программы. После вызо
ва ф у н к ц и и из DLL-библиотеки ее м о ж н о отключить. П р и одновремен
ном использовании нескольких DLL-библиотек это дает ощутимую э к о
н о м и ю памяти.
Для динамического подключения DLL-библиотеки применяются
функции Windows A P I . Windows API — это набор стандартных ф у н к ц и й ,
используемый для реализации взаимодействия с операционной системой.
Все ф у н к ц и и и з статически подключаемой DLL-библиотеки, кото
р ы е будут использоваться в приложении, первоначально д о л ж н ы быть
объявлены к а к внешние. П р и этом следует указать, если требуется, моди
фикатор вызова. Если ф у н к ц и я вызывается по индексу, то для нее следу
ет задать и м я , используемое в приложении и индекс ф у н к ц и и в DLL-биб¬
лиотеке.
Объявления внешних ф у н к ц и й выполняется в секции implementa
tion до использования этих ф у н к ц и й .
Объявление внешней ф у н к ц и и с ключевым словом external опреде
ляет, что будет применено статическое связывание.
Например:
f u n c t i o n F1 ( i : I n t e g e r ) :
Integer; s t d c a l l ;
external 'MyLib.dll';
П р и вызове ф у н к ц и и и з динамически подключаемой D L L - б и б л и о
теки, вместо определения и м е н и ф у н к ц и и к а к external, в случае статичес
кого связывания, следует определить н о в ы й т и п , соответствующий типу
вызываемой ф у н к ц и и , и создать переменную данного типа.
268
Лекция 25
Библиотека классов VCL среды проектирования Delphi.
Приложения и диалоги
Определение типа ф у н к ц и и или процедуры описывается так:
Новый_тип =function(список_параметров):тип_функции;
модификатор_доступа;
или
Новый_тип=procedure(список_параметров); модификатор доступа;.
Следующий пример иллюстрирует вызов ф у н к ц и и из динамически
подключаемой DLL-библиотеки:
u n i t Unit1;
interface
uses
Windows, Messages, S y s U t i l s , V a r i a n t s , Classes, Graphics,
C o n t r o l s , Forms, Dialogs, S t d C t r l s ;
type
TForm1 = class(TForm)
Button3: TButton;
procedure B u t t o n 3 C l i c k ( S e n d e r : TObject);
end;
TMyF1=function( i : I n t e g e r ) : I n t e g e r ; s t d c a l l ; { Создание
типа функции}
var
Form1: TForm1;
MyF1 : TMyF1;
{Объявление переменной типа функции}
implementation
{$R *.dfm}
procedure TForm1.Button3Click(Sender: TObject);
var
h: Integer;
begin
h:=LoadLibrary('MyLib. d l l ' ) ; // Динамическое подключение
if
h <> 0 then
begin
@MyF1:=GetProcAddress(h,'F1'); // Получение адреса функции
if
@MyF1 <> n i l then
ShowMessage(IntToStr(MyF1(20));
// Вызов Функции
FreeLibrary(h);
// Освобождение dll-библиотеки
end;
end;
end.
269
Курс
Введение в программирование
Создание и освобождение форм
Главная форма приложения
П о умолчанию при добавлении в проект новой ф о р м ы для нее в
главном файле приложения автоматически формируется строка кода для
создания формы.
Например:
Application.CreateForm
(TForm1, Form1);.
Для добавления в проект новой ф о р м ы достаточно выполнить к о
манду м е н ю File|New Form.
Окно свойств проекта позволяет определить:
• главную форму приложения — файл, в ы п о л н я е м ы й первым;
• список автоматически создаваемых форм;
• список доступных форм — чтобы их использовать, их надо будет со¬
здать.
Если приложение содержит много ф о р м , то для автоматического с о
здания всех ф о р м может н е хватить памяти. Более рационально создавать
ф о р м ы п о мере необходимости.
Для создания ф о р м ы используется метод Create.
Созданная форма может быть отображена:
• к а к о б ы ч н ы й диалог — вызовом метода Show;
• к а к модальный диалог — вызовом метода ShowModal.
Использование модальной формы
Выполнение модальной ф о р м ы завершается сразу после вызова м е
тода ShowModal, поэтому память и з под нее следует освобождать в вызыва¬
ю щ е й ф о р м е вызовом метода Free.
Например:
Form2:=TForm2.Create(self) ;
Form2.ShowModal;
Form2.Free;
Результат в ы п о л н е н и я модальной ф о р м ы устанавливается свойст
вом ModalResult командных кнопок. Д л я того чтобы проверить код ответа
(какая к н о п к а была нажата), следует сравнить значение, возвращаемое
методом ShowModal.
Например:
270
Лекция 25
Библиотека классов VCL среды проектирования Delphi.
Приложения и диалоги
i f Form2.ShowModal = mrOk then
// Нажата кнопка Ок
e l s e Abort;
// Завершение приложения
Для закрытия модального диалога не следует вызывать метод Close,
достаточно использовать командные к н о п к и с установленным значением
свойства ModalResult.
Использование немодальной формы
Время ж и з н и обычного немодального диалога неопределенно и не
завершается после вызова метода Show. Поэтому о б ы ч н ы й диалог следует
завершать в обработчике события OnClose.
Для вызова этого обработчика события м о ж н о вызвать метод Close
или выполнить щелчок м ы ш ь ю по соответствующей к н о п к е в строке за¬
головка окна.
Если перед запуском диалога он был создан (не является автомати
чески создаваемым), то после его закрытия следует освободить занимае
мую им память. Это выполняется в обработчике события OnClose вызовом
метода Release.
Классы стандартных диалогов
Страница Dialogs палитры компонентов содержит ряд компонентов,
предназначенных для реализации различных стандартных диалогов. Это
диалоги для открытия файла, сохранения файла, выбора цвета или ш р и ф
та, открытия или сохранения графического файла.
Стандартный диалог открывается при вызове метода Execute. П р и
выборе пользователем значения или щелчке пользователя на к н о п к е O K
возвращается значение True. Если пользователь нажал кнопку Cancel или
клавишу Escape, то выполнение стандартного диалога возвращает значе¬
н и е False. Для настройки появления и поведения диалога используется
свойство Options. Чтобы закрыть диалог программно, следует вызвать ме¬
тод CloseDialog.
В следующей таблице приведено описание стандартных диалогов,
доступных посредством страницы Dialogs палитры компонентов.
Класс
Описание действия
TOpenDialog
Отображает стандартный диалог Open
(имя выбранного файла указывается
в свойстве FileName)
271
Курс
Введение в программирование
TSaveDialog
Отображает стандартный диалог Save
TOpenPictureDialog
Отображает стандартный модальный диалог
для выбора и открытия графических файлов.
Этот диалог идентичен диалогу Open, н о имеет
дополнительно панель для просмотра
изображения
TSavePictureDialog
Отображает стандартный диалог
для сохранения графических файлов.
Этот диалог имеет панель для просмотра
изображения
TFontDialog
Выводит стандартный диалог Font,
используемый для определения шрифта,
размера и стиля отображения данных
TColorDialog
Отображает стандартный диалог Color
(выбранный цвет указывается в свойстве Color)
TPrintDialog
Отображает стандартный диалог Print
TPrinterSetupDialog
Отображает стандартный диалог Printer Setup
TFindDialog
Отображает стандартный диалог Find
TReplaceDialog
Отображает стандартный диалог Replace
Следующий пример иллюстрирует использование стандартного диа¬
лога для выбора и м е н и открываемого файла:
var F: TextFile; S: string;
begin
if OpenDialogl.Execute then / / Показать диалог Open
begin
AssignFile(F, OpenDialogl.FileName); / / Назначить
/ / файловой переменной и м я выбранного файла
Reset(F);
Readln(F, S);
/ / П р о ч и т а т ь первую строку файла
Editl.Text := S; / / Поместить строку в компонент TEdit
CloseFile(F);
/ / Закрыть файл
end;
end;
272
Лекция 26
Библиотека классов JDK. Основы построения интерфейса
пользователя на языке Java. События
Лекция 26. Библиотека классов JDK.
Основы построения интерфейса пользователя
на я з ы к е J a v a . С о б ы т и я
События
Типы событий
Событием в я з ы к е Java является объект. Все события м о ж н о разде
лить на две группы: события низкого уровня и семантические события.
К событиям низкого уровня относятся:
• события от клавиатуры и м ы ш и ;
• события от окна Windows;
• события от компонента;
• события от контейнера;
• события от перемещения фокуса ввода.
Семантические события являются событиями верхнего уровня
и з а в и с я т от и н и ц и и р о в а в ш е г о и х к о м п о н е н т а . О д н о и то ж е семан¬
тическое событие может быть и н и ц и и р о в а н о р а з н ы м и компонента¬
м и в ответ н а р а з л и ч н ы е д е й с т в и я п о л ь з о в а т е л я . С е м а н т и ч е с к о е с о
бытие можно рассматривать к а к более сложное событие, состоящее
из одного или нескольких событий низкого уровня. П р и м е р о м м о
ж е т с л у ж и т ь с о б ы т и е MenuEvent, и н и ц и и р у е м о е п р и в ы б о р е п у н к т а
меню.
Блоки прослушивания
В настоящее время в я з ы к е Java используется модель ожидаемых со
бытий. В этой модели инициируются только те события, которые были
объявлены объектами к а к ожидаемые.
Объект регистрирует блок прослушивания событий. Б л о к прослуши
вания — это интерфейс, который определяет набор методов-обработчи
ков событий, объявленных как ожидаемые события.
Регистрация блока прослушивания для компонента состоит в вызо
ве метода, начинающегося с префикса add, за которым идет и м я блока
прослушивания. И м е н а блоков прослушивания оканчиваются суффик¬
сом L i s t e n e r .
Для одного компонента м о ж н о зарегистрировать только один блок
прослушивания. Н о один блок прослушивания может использоваться не¬
сколькими компонентами одновременно.
273
Курс
Введение в программирование
Для того, чтобы компонент мог обрабатывать поступающие для него
события, следует:
1.
при объявлении класса указать наследуемые этим классом интер¬
ф е й с ы , содержащие методы-обработчики событий;
2.
добавить блоки прослушивания для компонентов;
3.
все методы-обработчики, объявленные в наследуемом интерфейсе,
реализовать в классе компонента.
Любой метод блока прослушивания имеет один параметр — объект,
производный от класса EventObject.
В классе EventObject определен метод Object getSource(), возвраща¬
ю щ и й объект, который и н и ц и и р о в а л событие. Некоторые классы, произ¬
водные от EventObject, имеют свои методы, которые определяют объект,
и н и ц и и р о в а в ш и й событие. Н а п р и м е р , класс ComponentEvent определяет
метод getComponent, возвращающий объект Component.
Классы-адаптеры
Чтобы зарегистрировать блок прослушивания, нужно указать его в
объявлении класса как наследуемый. В результате этого класс, наследую
щ и й д а н н ы й интерфейс, должен содержать код реализации всех объяв¬
ленных в интерфейсе методов. Если таких методов много, а нужен только
один, то все равно приходится включать код реализации каждого объяв
ленного в интерфейсе метода. Альтернативой такому подходу служит
п р и м е н е н и е классов адаптеров.
Класс-адаптер для интерфейса блока прослушивания содержит «пу
стую» реализацию всех его методов. Таким образом, при создании класса,
как производного от класса-адаптера, в качестве блока прослушивания
м о ж н о указывать класс-адаптер и включать реализацию только необходи¬
мых методов.
На следующей схеме приведен пример обработки события «щелчок
мышью» двумя способами: с п р и м е н е н и е м интерфейса блока прослуши
вания и с п р и м е н е н и е м адаптера блока прослушивания.
Применение интерфейса:
Применение класса адаптера:
p u b l i c c l a s s MyClass
p u b l i c c l a s s MyClass
implements MouseListener {
extends
myObject.addMouseListener(this);
MouseAdapter {
myObject.addMouseListener(this);
274
Библиотека классов JDK. Основы построения интерфейса
пользователя на языке Java. События
Лекция 26
/* Реализация всех методов
интерфейса MouseListener */
/* Переопределение только одного
метода адаптера MouseAdapter */
p u b l i c v o i d mousePressed(MouseEvent e) {
public void mouseClicked(MouseEvent e)
{
}
...// Код переопределяемого метода
p u b l i c void mouseReleased(MouseEvent e) {
}
}
p u b l i c v o i d mouseEntered(MouseEvent e) {
}
}
p u b l i c v o i d mouseExited(MouseEvent e ) {
}
p u b l i c v o i d mouseClicked(MouseEvent e) {
...// Код метода
}
}
Приведенный в ы ш е пример в практическом плане имеет один недо¬
статок. П р и программировании классы приложений в большинстве слу¬
чаев создаются как производные от классов Frame, Panel, JFrame, а классы
апплетов — от класса Applet или JApplet. Н о в я з ы к е Java реализовано
только простое наследование, позволяющее иметь всего один наследуе¬
м ы й класс.
Поэтому, чтобы применять классы-адаптеры, м о ж н о использовать
два способа реализации:
• использование внутренних классов:
p u b l i c c l a s s MyClass extends Applet {
// Создание объекта класса адаптера:
myObject.addMouseListener(new MyClassAdapter());
c l a s s MyClassAdapter extends MouseAdapter
{//Объявление
//внутреннего класса адаптера
p u b l i c v o i d mouseClicked(MouseEvent e) {
// Реализация методов класса адаптера
}
}
275
...
}
Курс
Введение в программирование
• использование а н о н и м н ы х внутренних классов:
p u b l i c c l a s s MyClass extends A p p l e t {
// Создание объекта и реализаци класса адаптера:
myObject.addMouseListener(new MouseAdapter() {
// Реализация переопределяемых методов класса адаптера
p u b l i c v o i d mouseClicked(MouseEvent e) {
}
});
}
}
Для того чтобы реализовать п р и м е н е н и е класса-адаптера с исполь¬
зованием вложенного класса, следует:
1.
добавить блок прослушивания компонента и указать в качестве п а
раметра код new имя_внутреннего_класса
( н а п р и м е р , addMouseListener(new MouseAdapter() );
2.
добавить код с объявлением внутреннего класса, включающий реа¬
лизацию требуемых методов обработчиков событий
( н а п р и м е р , c l a s s MyClassAdapter extends MouseAdapter {
p u b l i c v o i d mouseClicked(MouseEvent e) {
...
}}.
Для того чтобы реализовать п р и м е н е н и е класса адаптера с использо¬
ванием вложенного а н о н и м н о г о класса-адаптера, следует:
1.
добавить блок прослушивания компонента и указать в качестве п а
раметра код new им я _класса_адаптера { }
( н а п р и м е р , addMouseListener(new MyClassAdapter(){ } ) ;
2.
вставить в фигурные скобки после и м е н и класса адаптера код пере¬
определяемых методов
(например, {
p u b l i c v o i d mouseClicked(MouseEvent e) {
...
}}.
Использование а н о н и м н ы х вложенных классов значительно улуч¬
шает читаемость кода.
Блоки прослушивания пакета JDK
Пакет java.util содержит интерфейс EventListener, который наследу
ется всеми блоками прослушивания.
Для различных классов компонентов предназначаются р а з н ы е и н
терфейсы блоков прослушивания.
В следующей таблице приведены некоторые интерфейсы блоков
прослушивания, наследуемые от интерфейса EventListener.
276
Лекция 26
Библиотека классов JDK. Основы построения интерфейса
пользователя на языке Java. События
Интерфейс
Пакет
Action
javax.swing
Описание
Расширяет интерфейс A c t i o n L i s t e n e r ,
позволяя нескольким компонентам
использовать одни и те же обработчики
событий
ActionListener
java.awt.event
Этот блок прослушивания регистрируется
методом addActionListener. При возникно
вении события «действие» вызывается
метод a c t i o n P e r f o r m e d ( A c t i o n E v e n t e)
компонента, зарегистрировавшего данный
блок прослушивания. Интерфейс исполь
зуется для обработки событий меню,
кнопок и т.п.
AdjustmentListener
java.awt.event
Используется для получения
регулируемых событий
AncestorListener
javax. swing. event
Интерфейс поддерживает уведомления
при изменении компонента класса
JComponent или одного из его предков.
Это касается перемещения компонента,
перехода из видимого состояния в неви
димое или обратно, выполнения метода
s e t V i s i b l e ( ) , а также при добавлении и
удалении компонентов из иерархии
CaretListener
javax.swing.event
Используется при изменении позиции
ввода в текстовых компонентах. Этот
интерфейс реализован классом
javax.swing.text.JTextComponent.AccessibleJTextComponent
CellEditorListener
javax. swing. event
Используется для отслеживания изме
нений в редактируемой ячейке (CellEditor),
касающихся завершения или отмены
редактирования. Этот интерфейс
реализован следующими классами:
JTable, J T a b l e . A c c e s s i b l e J T a b l e ,
BasicTreeUI. C e l l E d i t o r H a n d l e r
ChangeListener
javax. swing. event
Определяет объект, выполняющий
прослушивание событий ChangeEvent.
Интерфейс объявляет всего один метод:
v o i d stateChanged(ChangeEvent e ) . Этот
интерфейс реализован несколькими
классами, включая:
JMenultem.AccessibleJMenultem,
BasicButtonListener,
JTabbedPane.AccessibleJTabbedPane.
ContainerListener
java.awt.event
Интерфейс объявляет два метода:
public void
277
Курс
Введение в программирование
componentAdded(ContainerEvent e)
и p u b l i c vo i d
componentRemoved(ContainerEvent e) ,
вызываемые при добавлении компонента
в контейнер или при удалении из
контейнера. Для этого интерфейса
реализован класс-адаптер Containe rAdapte r
DocumentListener
javax.swing.event
Интерфейс используется при изменении
текстового документа
DragGestureListener
java.awt.dnd
Интерфейс используется при инициа
лизации процесса перетаскивания
объекта
DragSourceListener
java.awt.dnd
Интерфейс используется для реализации
механизма перетаскивания и сбросаобъектов (Drag & Drop). В этот интер
фейсе объявлены методы для отслежи
вания действий пользователя по пере¬
мещению объекта. Этот интерфейс
реализован классом DragSourceContext
DropTargetListener
java.awt.dnd
Интерфейс может быть использован для
обработки событий, инициируемых в то
время, когда объект находится
над местом сброса
FocusListener
java.awt.event
Интерфейс используется для обработки
событий получения или потери фокуса
компонентом. Блок прослушивания
регистрируется методом addFocusListene r.
Для этого интерфейса реализован класс
адаптер FocusAdapter
ItemListener
java.awt.event
Интерфейс используется для обработки
события выделения элемента и объяв
ляет только один метод p u b l i c v o i d
itemStateChanged(ItemEvent e). Блок
прослушивания регистрируется
методом a d d I t e m L i s t e n e r
KeyListener
java.awt.event
Интерфейс используется для обработки
событий от клавиатуры. Блок прослу¬
шивания регистрируется методом
a d d K e y L i s t e n e r . Для интерфейса реали
зован класс-адаптер KeyAdapter
L i s t S e l e c t i o n L i s t e n e r javax. swing. event
Используется для обработки события,
инициирующегося при изменении
области выделения
MenuDragMouseListener javax.swing.event
Интерфейс объявляет четыре метода
обработчика событий, инициируемых
278
Библиотека классов JDK. Основы построения интерфейса
пользователя на языке Java. События
Лекция 26
при перемещении и сбросе в области
компонентов меню
MenuKeyListener
javax.swing.event
Интерфейс используется для обработки
событий, инициируемых для меню при
вводе комбинаций клавиш
MenuListener
javax.swing.event
Определяет блок прослушивания
с обработчиками событий для меню
MouseInputListener
javax.swing.event
Интерфейс наследует интерфейсам
MouseMotionListener (методы:
mouseDragged, mouseMoved)и
M o u s e L i s t e n e r (методы: mouseClicked,
mouseEntered, mouseExited,
mousePressed, mouseReleased). Этот
интерфейс используется для обработки
любых событий, инициируемых
действиями мыши
MouseListener
java.awt.event
Интерфейс, используемый для обработки
событий от щелчков мышью. Блок
прослушивания регистрируется методом
addMouseListener. Для интерфейса
реализован класс-адаптер MouseAdapter
MouseMotionListener
java.awt.event
Интерфейс, используемый для обработки
событий от перемещения курсора
мыши. Блок прослушивания регистри
руется методом
addMouseMotionListener. Для интерфейса
реализован класс-адаптер
PopupMenuListener
javax.swing.event
Интерфейс определяет методы блока
прослушивания для всплывающих
меню (popup-меню).
MouseMotionAdapter.
PropertyChangeListener
j a v a . beans
Интерфейс определяет метод обработчик
события, вызываемый при изменении
свойства бина
TableColumnModelListener javax. swing .event
Интерфейс, используемый для прослу
шивания событий, изменяющих
TableColumnModel. К таким событиям
относятся добавление, удаление,
изменение размера и перемещение
столбца таблицы. Этот интерфейс
реализован классами JTable,
J T a b l e . A c c e s s i b l e J T a b l e и JTableHeader
TableModelListener
javax. swing. event
Интерфейс, используемый для прослу
шивания событий, которые изменяют
TableModel
279
Курс
Введение в программирование
TextListener
java.awt.event
void
t e x t V a l u e C h a n g e d ( T e x t E v e n t e) ,
Интерфейс объявляет метод
вызываемый при изменении значения
текстовых компонентов, таких, как
TextArea,
TextField
T r e e E x p a n s i o n L i s t e n e r javax.swing.event
Интерфейс, используемый для прослу
шивания событий распахивания или
сворачивания дерева
TreeModelListener
Интерфейс, используемый для прослу
шивания событий, которые изменяют
javax. swing. event
TreeModel
T r e e S e l e c t i o n L i s t e n e r javax.swing.event
Интерфейс объявляет метод,
вызываемый при изменении
выделенного элемента дерева
WindowListener
Интерфейс используется для обработки
событий окна. Блок прослушивания
регистрируется методом
addWindowListener. Для интерфейса
реализован класс-адаптер WindowAdapter
java.awt.event
Методы — обработчики событий
События окна
Методы — обработчики событий окна объявляются в интерфейсе
WindowListener. Д л я д а н н о г о и н т е р ф е й с а существует класс адаптер
WindowAdapter .
Для того чтобы отслеживать все события окна, м о ж н о создать класс
окна, наследуемый от интерфейса WindowListener .
Например:
p u b l i c c l a s s MyWindowListener
{
public
public
public
public
public
void
void
void
void
void
extends Frame
implements WindowListener
windowClosing(WindowEvent e) { }
windowClosed(WindowEvent e) { }
windowOpened(WindowEvent e) { }
windowIconified(WindowEvent e) { }
windowDeiconified(WindowEvent e) { }
p u b l i c v o i d windowActivated(WindowEvent e) { }
p u b l i c v o i d windowDeactivated(WindowEvent e) { }
}
280
Лекция 26
Библиотека классов JDK. Основы построения интерфейса
пользователя на языке Java. События
Если надо отслеживать все события окна приложения или апплета,
то блок прослушивания следует добавить для объекта t h i s / .
Например:
addWindowListener(this);
Если надо отслеживать все события окна, создаваемого в процессе
в ы п о л н е н и я приложения или апплета, то сначала надо создать объект
«окно», а затем добавить для него блок прослушивания.
Например:
myFrame = new Frame("Заголовок окна");
myFrame.addWindowListener(this);
Интерфейс WindowListener объявляет следующие методы, вызывае
м ы е для события WindowEvent:
• WindowActivated — метод обработки события, вызываемый при акти¬
визации окна пользователем.
• WindowClosed — метод обработки события, вызываемый при закры
тии окна вследствии вызова метода d i s p o s e ( ) , который освобождает
ресурсы экрана.
• WindowClosing — метод обработки события, вызываемый при закры¬
тии окна пользователем с п о м о щ ь ю системного меню.
• WindowDeactivated — метод обработки события, вызываемый при по¬
тери о к н о м фокуса.
• windowDeiconif ied — метод обработки события, вызываемый при и з
м е н е н и и состояния окна из свернутого в нормальное.
• windowIconif ied — метод обработки события, вызываемый при изме
н е н и и состояния окна из нормального в свернутое.
• windowOpened — метод вызывается один раз при открытии окна.
События от клавиатуры
Методы обработчики событий от клавиатуры объявляются в интер
фейсе KeyListener, для которого существует класс адаптер KeyAdapter.
Событие от клавиатуры происходит для компонента, имеющего ф о
кус. События от клавиатуры являются низкоуровневыми событиями.
Интерфейс KeyListener объявляет следующие методы обработчики
для события KeyEvent:
• v o i d keyTyped(KeyEvent e ) ;
• v o i d keyPressed(KeyEvent e ) ;
• v o i d keyReleased(KeyEvent e)
// Ввод символа
// Нажатие клавиши
// Отпускание клавиши
281
Курс
Введение в программирование
Для получения и н ф о р м а ц и и о коде нажатой к л а в и ш и следует и с
пользовать методы класса KeyEvent.
Класс KeyEvent определен в иерархии классов Java следующим образом:
П р и нажатии и л и отпускании к л а в и ш и метод getKeyCode возвращает
значение кода нажатой клавиши.
М е т о д getKeyChar возвращает з н а ч е н и е с и м в о л а Unicode и л и
CHAR_UNDEFINED.
П р и обработки события ввода (метод void keyTyped(KeyEvent e) )
м о ж н о получить значение введенного с клавиатуры символа в формате
Unicode и л и CHAR_UNDEFINED.
Клавиатурные к о м б и н а ц и и обрабатываются в методах:
• v o i d keyPressed(KeyEvent e) и
• v o i d keyReleased(KeyEvent e).
Н а п р и м е р , нажатие к л а в и ш Shift+B м о ж н о отследить в методе
keyPressed (событие KEY_PRESSED): п р и первом вызове метода будет возвра
щ е н код к л а в и ш и Shift — VK_SHIFT, а п р и втором вызове метода — код кла
в и ш и A — VK_B. И только затем произойдет вызов метода keyTyped.
Н а следующей схеме приведен алгоритм обработки событий от кла¬
виатуры.
Нажатая
клавиша
Вызываемые
методы
обработки
события
Методы класса
KeyEvent, используемые
для получения
информации
Возвращаемое
методом
значение
Shift+A
keyPressed
getKeyChar()
getKeyCode()
getModifiers()
символ = ' '
код = 16 (Shift)
модификатор = 1
keyPressed
getKeyChar()
getKeyCode()
getModifiers()
символ ='B'
код = 66 (B)
модификатор = 1
282
Библиотека классов JDK. Основы построения интерфейса
пользователя на языке Java. События
Лекция 26
keyTyped
getKeyChar()
getKeyCode()
getModifiers()
символ = 'B'
код = 0
модификатор = 0
keyReleased
getKeyChar()
getKeyCode()
getModifiers()
символ = 'A'
код = 66 (B)
модификатор = 0
keyReleased
getKeyChar()
getKeyCode()
getModifiers()
символ = ' '
код = 16 (Shift)
модификатор = 0
В классе KeyEvent определены виртуальные коды д л я всех клавиш
клавиатуры. К таким кодам относятся:
• Коды ц и ф р : от VK_0 до VK_9 ( A S C I I - к о д ы ц и ф р от '0' д о '9' (0x30 —
0x39)).
• Коды букв: от VK_A д о VK_Z (ASCII-коды букв от 'A' д о 'Z' (0x41 —
0x5A)).
• К о д ы N U M P A D - к л а в и а т у р ы : от VKNUMPAD0 д о VKNUMPAD9.
• Коды управляющих и функциональных клавиш: от VK_F1 д о VKF24,
VK_NUM_LOCK, VK PRINTSCREEN, VK_INSERT, VK HELP, VK DELETE, VK_ENTER,
VK_BACK_SPACE, VK_TAB, VK_CANCEL, VK_CAPS_LOCK, VK_ESCAPE, VK_SPACE,
VK_PAUSE.
• К о д ы п е р е м е щ е н и я п о з и ц и и : VK_PAGE_UP, VK_PAGE_DOWN, VK_END, VK_HOME,
VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN.
• К о д ы - м о д и ф и к а т о р ы : VK_SHIFT, VK_ALT, VK_CONTROL.
• К о д ы символов: VK_DOLLAR, VK_COMMA, VK_MINUS, VK_PERIOD, VK_SLASH,
VK_SEMICOLON, VK_EQUALS, VK_OPEN_BRACKET ( о т к р ы в а ю щ а я с к о б к а ) ,
VK_BACK_SLASH ( о б р а т н ы й с л э ш ) , VK_CLOSE_BRACKET
(закрывающая
скобка).
Класс KeyEvent содержит следующий набор методов, предназначен¬
ных для определения кодов нажатых клавиш:
• GetKeyChar — возвращает символ Unicode, соответствующий нажа
той клавиши, с учетом регистра и я з ы к а клавиатуры.
• GetKeyCode — возвращает код нажатой к л а в и ш и .
• G e t K e y M o d i f i e r s T e x t — возвращает строку, содержащую описание
кода-модификатора (например, «Ctrl+Shift»).
• GetKeyText — возвращает строку, содержащую описание кода (на¬
пример, «F1», «PageUp» или «D»).
• I s A c t i o n K e y — определяет, была ли нажата клавиша action-ключа, та
кая, как P G U P , P G D N , F 1 , F2 и т.п.
• ParamStri ng — возвращает строку параметров, определяющих данное
событие.
283
Курс
Введение в программирование
• SetKeyChar — устанавливает значение, равное значению символа
Unicode.
• SetKeyCode — устанавливает значение, равное значению кода клавиши.
• SetModif i e r s — устанавливает значение кода модификатора.
• SetSource — определяет источник события KeyEvent.
Наряду с о п и с а н н ы м и методами, м о ж н о использовать методы, н а
следуемые от класса java.awt.event.InputEvent, включая следующие:
• boolean i s A l t D o w n ( )
• boolean i s S h i f t D o w n ( )
• boolean i s C o n t r o l D o w n ( )
// Нажата клавиша A l t
// Нажата клавиша S h i f t
// Нажата клавиша C t r l
События действия
Событие действия — это семантические событие, зависящее от типа
компонента. Так, для командной к н о п к и событием действия будет щел¬
ч о к м ы ш ь ю или нажатие клавиши Enter в момент, когда к н о п к а имеет фо¬
кус. Д л я компонентов типа «список» событием действия является выбор
элемента, для компонентов «меню» — выбор пункта м е н ю , а для компо¬
нентов «текстовое поле» — нажатие клавиши Enter.
События действия определяются в интерфейсе A c t i o n L i s t e n e r . Этот
интерфейс задает единственный метод обработки события actionPerformed,
вызываемый при возникновении для компонента сооответствующего его
типу события действия.
Для того чтобы обрабатывать событие действия, м о ж н о выполнить
следующее:
1.
Создать класс, наследующий интерфейс A c t i o n L i s t e n e r .
Например:
p u b l i c c l a s s MyFrame extends Frame implements A c t i o n L i s t e n e r
2.
}.
Зарегистрировать блок прослушивания события действия для ком¬
понента.
Например:
myButton.addActionListener(this).
3.
{
Переопределить метод actionPerformed:
Например:
p u b l i c v o i d actionPerformed(ActionEvent e) {
T o o l k i t . g e t D e f a u l t T o o l k i t ( ) . b e e p ( ) ; }.
284
Лекция 26
Библиотека классов JDK. Основы построения интерфейса
пользователя на языке Java. События
Метод обработки события действия получает параметр типа Act ionEvent.
Класс ActionEvent определен в иерархии классов Java следующим об¬
разом:
Класс ActionEvent определяет и наследует несколько полезных мето
дов, включая следующие:
• GetActionCommand — метод возвращает строку, ассоциируемую с д а н
н ы м событием действия. Если для объекта был ранее вызван метод
setActionCommand, устанавливающий такую строку, то эта строка и бу¬
дет возвращена. В противном случае, возвращаемое значение зави¬
сит от типа к о м п о н е н т а /
• GetModif i e r s — возвращает число, определяющее, была ли нажата
клавиша-модификатор п р и в о з н и к н о в е н и и события действия. Для
определения кода нажатой к л а в и ш и - м о д и ф и к а т о р а м о ж н о исполь
зовать к о н с т а н т ы SHIFT_MASK, CTRL_MASK и ALT_MASK.
Например, если при в о з н и к н о в е н и и события действия была нажата
клавиша Shift, то следующее выражение не будет равно нулю:
a c t i o n E v e n t . g e t M o d i f i e r s ( ) & ActionEvent.
SHIFT_MASK.
• getSource — метод возвращает объект, для которого было иницииро¬
вано событие.
285
Курс
Введение в программирование
Лекция 27. Библиотека классов JDK. Основы
п о с т р о е н и я и н т е р ф е й с а п о л ь з о в а т е л я на я з ы к е
Java. Компоновки и элементы управления
Менеджеры компоновок
Применение компоновок
При проектировании интерфейса пользователя с использованием
языка Java компоненты размещаются в контейнерах. Самым простым при
мером контейнера может служить окно формы (класс Frame). В общем слу
чае любой класс, наследуемый от класса контейнера java.awt.Container,
является контейнером.
В я з ы к е Java для «плавающего» размещения компонентов, завися¬
щего от размеров окна и размеров самих компонентов, введены классы
компоновок.
К о м п о н о в к а определяет порядок расположения компонентов на эк¬
ране. Перед отображением объектов-контейнеров, содержащих другие
к о м п о н е н т ы , вызывается менеджер к о м п о н о в к и . О н располагает к о м п о
ненты на экране в соответствующем порядке. Используемый менеджер
к о м п о н о в к и указывается вызовом метода setLayout. Если менеджер к о м
поновки н е указан я в н о , то выбирается тот, что используется п о умолча
н и ю для данного класса контейнера.
Для того чтобы отключить использование менеджеров компоновки и пе
рейти к явному указанию координат, следует вызвать метод setLayuot(null).
Пакеты java.awt и javax.swing предоставляют следующие классы
менеджеров компоновки:
• java.awt.FlowLayout — создает последовательное размещение объ¬
ектов с указанным выравниванием и заданными между этими объек¬
тами интервалами.
• java.awt.GridLayout — создает табличное размещение объектов с за
д а н н ы м числом строк и столбцов, объекты располагаются последо¬
вательно слева направо.
• j ava. awt. G ridBagLayout — создает гибкое табличное размещение объ
ектов, позволяя размещать один компонент в нескольких ячейках.
• java.awt.BorderLayout — создает размещение объектов по краю кон¬
тейнера (вверху, внизу, слева, справа и в центре).
• java.awt.CardLayout — создает к о м п о н о в к у контейнера, отображая
о д н о в р е м е н н о только о д и н компонент. К а к п р а в и л о , в качестве
к о м п о н е н т для д а н н о г о менеджера к о м п о н о в к и выступают панели.
286
Лекция 27
Библиотека классов JDK. Основы построения интерфейса
пользователя на языке Java. Компоновки и элементы управления
• j a v a x . s w i n g . S c r o l l P a n e L a y o u t — позволяет размещать к о м п о н е н т ы
на девяти различных областях; является к о м п о н о в к о й по умолчанию
для класса ScrollPane.
• javax.swing.ViewportLayout — является к о м п о н о в к о й по умолчанию
для класса Jviewpo rt.
• javax.swing.BoxLayout — является к о м п о н о в к о й по умолчанию для
класса Box.
• javax.swing.OverlayLayout — позволяет размещать к о м п о н е н т ы один
над другим.
Д л я и с п о л ь з о в а н и я к о н к р е т н о г о м е н е д ж е р а к о м п о н о в к и следует
создать объект д а н н о г о к л а с с а и установить с о з д а н н у ю к о м п о н о в к у
д л я д а н н о г о к о н т е й н е р а , а затем д о б а в и т ь в к о н т е й н е р другие компо¬
ненты.
Например:
GridBagLayout g r i d B a g L a y o u t l = new GridBagLayout();
this.setLayout(gridBagLayout1);
Button button1 = new Button();
button1.setLabel("Кнопка 1");
this.add(button1,
new Gr i d B a g C o n s t r a i n t s ( 0 , 0 , 3, 1, 0.0, 0.0,
GridBagConstraints.CENTER,
GridBagConstraints.NONE,
new I n s e t s ( 0 , 0 , 0 , 0 ) ,
315, 0 ) ) ;
Метод setLayout следует квалифицировать именем контейнера, для
которого устанавливается компоновка. Для класса контейнера, в котором
выполняется д а н н ы й метод, м о ж н о использовать ссылку t h i s . В случае
предварительного создания объекта «менеджер компоновки», его следует
указать как параметр метода setLayout. В противном случае в качестве па
раметра метода setLayout следует указать оператор создания анонимного
объекта «менеджер компоновки».
Например:
this.setLayout(gridLayout1);
// или
this.setLayout(new
GridLayout());
П р и использовании панели типа Panel методы объекта «менеджер
к о м п о н о в к и » в ы з ы в а ю т с я с т а н д а р т н ы м образом им я _объекта_менеджер_компоновки. им я_метода.
287
Курс
Введение в программирование
Например:
cardLayout1.show(Panel1,"Panel0"); .
П р и использовании панели типа JPanel методы объекта «менеджер
компоновки» вызываются с использованием метода getLayout.
Например:
((CardLayout)jPanel2.getLayout()).show(j Panel2,"jPanel0");
Классы компоновок
Класс BorderLayout
Менеджер к о м п о н о в к и BorderLayout разбивает контейнер на пять
областей и располагает добавляемые в контейнер объекты по краям (се¬
вер, юг, запад, восток) и в центре.
Каждая область указывается соответствующей константой: NORTH, SOUTH,
EAST, WEST и CENTER. Если в методе add отсутствует строка, указывающая распо
ложение компонента, то по умолчанию используется значение CENTER.
На рис. 1. приведен внешний вид, реализуемый менеджером компоновки
BorderLayout для пяти кнопок, которые расположены в контейнере — апплете.
Applet started.
Рис. 1. Менеджер к о м п о н о в к и BorderLayout
Следующий
код
иллюстрирует
BorderLayout:
import j a v a . a p p l e t . A p p l e t ;
import java.awt. *;
288
использование
компоновки
Лекция 27
Библиотека классов JDK. Основы построения интерфейса
пользователя на языке Java. Компоновки и элементы управления
p u b l i c c l a s s MyApplet extends Applet {
p u b l i c MyApplet() {
try { jbInit();}
c a t c h ( E x c e p t i o n e) {
} }
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [ ] args) {
MyApplet myApplet1 = new MyApplet(); }
p r i v a t e v o i d j b I n i t ( ) throws Exception {
setLayout(new B o r d e r L a y o u t ( ) ) ;
add(new B u t t o n ( " N o r t h " ) , BorderLayout.NORTH);
add(new B u t t o n ( " S o u t h " ) , BorderLayout.SOUTH);
add(new B u t t o n ( " E a s t " ) , BorderLayout.EAST);
add(new Button("West"), BorderLayout.WEST);
add(new B u t t o n ( " C e n t e r " ) , BorderLayout.CENTER);
}
}
Класс BorderLayout предоставляет ряд методов, включая следующие:
• GetHgap - возвращает расстояние в пикселях между компонентами по
горизонтали.
• SetHgap — устанавливает расстояние в пикселях между компонента¬
ми по горизонтали.
• GetVgap — возвращает расстояние в пикселях между компонентами
по вертикали.
• SetVgap — устанавливает расстояние в пикселях между компонента¬
ми по вертикали.
Класс CardLayout
Класс CardLayout определяет менеджер к о м п о н о в к и для контейнера,
который может содержать несколько страниц («карт») и для которого од¬
н о в р е м е н н о может быть видна только одна карта.
Класс CardLayout предоставляет ряд методов, включая следующие:
• GetHgap — определяет отступ по горизонтали.
• GetVgap — определяет отступ по вертикали.
• F i rst — активизирует первую страницу контейнера.
• Last — активизирует последнюю страницу контейнера.
• Next — а к т и в и з и р у е т с л е д у ю щ у ю с т р а н и ц у к о н т е й н е р а в ц и к л и
ческом порядке (после последней карты активизируется первая
карта).
• Previous — активизирует предыдущую страницу контейнера в ц и к
лическом порядке.
• Show — активизирует компонент указанного контейнера.
289
Курс
Введение в программирование
Например:
// Для контейнера типа J P a n e l
v o i d j B u t t o n 1 _ a c t i o n P e r f o r m e d ( A c t i o n E v e n t e) {
((CardLayout)jPanel1.getLayout()).next(jPanel1);
}
// Дл
контейнера типа Panel
v o i d b u t t o n 1 _ a c t i onPerformed(Acti onEvent e) {
cardLayout1.next(panel1);
}
Класс FlowLayout
Менеджер к о м п о н о в к и FlowLayout размещает добавляемые в контей
нер к о м п о н е н т ы последовательно слева направо. К о м п о н е н т ы могут
быть размещены в нескольких последовательных рядах.
На рис. 2 приведены два результата применения этой к о м п о н о в к и
при изменении размеров контейнера.
Рис.2. П р и м е н е н и е к о м п о н о в к и FlowLayout
щие
•
•
•
Класс FlowLayout предоставляет следующие константы, определяю¬
выравнивание компонентов:
CENTER — по центру.
LEFT — по левому краю.
RIGHT — по правому краю.
Класс FlowLayout предоставляет ряд методов, включая следующие:
290
Библиотека классов JDK. Основы построения интерфейса
пользователя на языке Java. Компоновки и элементы управления
Лекция 27
• SetAlignment — устанавливает выравнивание компонентов для дан¬
н о й к о м п о н о в к и . Параметр метода может принимать следующие
з н а ч е н и я : FlowLayout. LEFT, FlowLayout. RIGHT и FlowLayout.CENTER.
• GetHgap — определяет расстояние между компонентами по горизонтали.
• SetHgap — устанавливает расстояние между компонентами п о гори¬
зонтали.
• GetVgap — определяет расстояние между компонентами по вертикали.
• SetVgap — устанавливает расстояние между компонентами по вертикали.
Класс GridLayout
Этот класс позволяет размещать компоненты в контейнере в виде табли
цы. В каждой ячейке таблицы может быть размещен только один компонент.
Размер всех ячеек таблицы одинаков. Количество строк и столбцов
таблицы определяется или в конструкторе, или вызовом методов setColumns
и setRows. При этом, если эти значения не равны нулю, то количество столб
цов является величиной вычисляемой и зависит от общего числа компонен
тов, добавленных на компоновку, и указанного числа строк. И только в том
случае, если количество строк задано равным нулю, заданное количество
столбцов будет учитываться менеджером компоновки.
На рис. 3 приведены примеры использования компоновки GridLayout.
ЕШ Applet Viewer: MyApplet. class ЩИ1ЕЗ
Applet
^ A p p l e t Viewer: MyApplet.class
[
| |
Applet
Кнопка 1
Кнопка 2
Кнопка 3
Д л и н н а я кнопка 4
Кнопка 1
Кнопка 2
Кнопка 3
Д л и н н а я кнопка 4
Кнопка5
Applet started.
Кнопка5
Applet started.
Рис.3. П р и м е р к о м п о н о в к и GridLayout
Для к о м п о н о в к и GridLayout следует определять и л и количество
строк, или количество столбцов.
Например:
this.setLayout(gridLayout1);
gridLayout1.setRows(3);
291
Курс
Введение в программирование
Класс GridBagLayout
Этот класс используется менеджером к о м п о н о в к и GridBagLayout и
определяет требования к размещению компонентов.
К о м п о н о в к а GridBagLayout позволяет размещать к о м п о н е н т ы в ячей
ках таблицы. Н о , в отличие от менеджера к о м п о н о в к и GridLayout, ячейки
таблицы могут различаться к а к по ш и р и н е , так и по высоте. Размещаемые
к о м п о н е н т ы могут занимать несколько ячеек.
Область, занимаемая компонентом, называется областью отображе
ния. Ее размеры определяются значениями переменных g ridwidth и g ridheight (количество я ч е е к п о г о р и з о н т а л и и п о в е р т и к а л и ) класса
GridBagConstraints.
Отступами (insets) называется расстояние между областью отобра
ж е н и я и действительной областью, занимаемой компонентом.
Н а рис. 4 приведен пример к о м п о н о в к и , в которой к н о п к а 3 занима
ет 9 ячеек, н о размер к н о п к и меньше размера области отображения.
Sl
l-l.nl.х|
1
•
2
•
4
Область
отображения
ячеек
3
5
6 |
•
Рис. 4. Отступы, устанавливаемые объектом GridBagConstraints
Если область отображения отличается от размера компонента, то для
определения требований к размещению используется переменная f i l l .
Е с л и р а з м е р р а з м е щ а е м о г о к о м п о н е н т а м е н ь ш е р а з м е р а области
о т о б р а ж е н и я , т о д л я у к а з а н и я р а з м е щ е н и я к о м п о н е н т а используется
п е р е м е н н а я anchor, к о т о р а я м о ж е т п р и н и м а т ь одно и з с л е д у ю щ и х з н а
чений:
•
GridBagConstraints.CENTER
•
GridBagConstraints.NORTH
• GridBagConstraints.NORTHEAST
•
GridBagConstraints.EAST
• GridBagConstraints.SOUTHEAST
•
GridBagConstraints.SOUTH
•
GridBagConstraints.SOUTHWEST
•
GridBagConstraints.WEST
292
Лекция 27
Библиотека классов JDK. Основы построения интерфейса
пользователя на языке Java. Компоновки и элементы управления
•
GridBagConstraints.NORTHWEST.
П е р е м е н н а я f i l l к л а с с а G r i d B a g C o n s t r a i n t о п р е д е л я е т , следует
ли изменять размер компонента, и может принимать следующие
значения:
• GridBagConstraint.NONE — размер компонента н е изменять (значе
ние, используемое по умолчанию);
• GridBagConstraint.HORIZONTAL — изменить размер по горизонтали, н о
не изменять его высоту;
• GridBagConstraint.VERTICAL — изменить размер п о вертикали, н о н е
изменять его ширину;
• GridBagConstraint.BOTH — увеличить размеры компонента до разме
ра области отображения.
П е р е м е н н ы е g r i d h e i g h t и g r i d w i d t h класса GridBagConstraint опреде
ляют число ячеек в столбце и л и строке соответственно. П р и этом к о н
станта GridBagConstraints. REMAINDER указывает, что компонент будет п о
следним в столбце (строке), а константа GridBagConstraints. RELATIVE ука
зывает, что компонент будет ближайшим к последнему.
Конструктор GridBagConstraints(int gridx, i n t gridy,
i n t gridwidth, i n t gridheight,
double weightx, double weighty,
i n t anchor, i n t f i l l ,
Insets insets,
int
ipadx,
i n t ipady)
создает
объект требований к р а з м е щ е н и ю компонента, используемый менедже
р о м к о м п о н о в к и , со всеми п о л я м и , и м е ю щ и м и заданные значения.
Компоненты графического интерфейса пользователя
Панели
Java-приложение создается к а к иерархия вложенных компонентов.
Наверху этой иерархии могут находится к о м п о н е н т ы классов Frame,
JFrame, Applet или JApplet. Классы панелей используются к а к контейнеры
для размещения других компонентов, в числе которых могут быть и сами
панели. Пакет оконного интерфейса java.awt содержит один класс панели
— Panel. Д л я добавления компонентов на панель класса Panel следует вы¬
полнить метод add, квалифицировав его именем панели.
Пакет облегченных swing-компонентов предоставляет несколько
классов панелей, включая следующие классы:
• JRootPane
• JPanel
293
Курс
Введение в программирование
•
•
•
•
•
JTabbedPane
JScrollPane
JSplitPane
JOptionPane
JToolbar .
П р и использовании менеджеров к о м п о н о в к и с панелями из пакета
java. swing для получения ссылки на панель следует использовать метод
getLayout.
Например:
((CardLayout)j
Panel1.getLayout()).next(jPanel1);
Пакет javax.swing содержит интерфейс RootPaneContainer, реализуе
м ы й классами JApplet, JFrame, JInternalFrame, JWindow и J D i a l o g .
При добавлении компонентов в контейнер, использующий интер
фейс RootPaneContainer, метод add надо квалифицировать следующим об¬
разом:
frame.getContentPane() .add(child).
Класс JRootPane используется всеми панелями пакета javax.swing.
О н позволяет размещать содержимое панели на нескольких уровнях.
JRootPane представояет четыре уровня:
• ContentPane — используется для отображения компонентов.
• MenuBar — необязательный уровень, на котором м о ж н о размещать
к о м п о н е н т ы меню.
• LayeredPane — используется для управления contentPane и menuBar.
• GlassPane — самый ближайший к пользователю уровень. П о умолча¬
н и ю о н невидим. glassPane, к а к правило, используется для отобра
ж е н и я графики или каких-либо всплывающих компонентов. К о м
поненты этого уровня перекрывают к о м п о н е н т ы , расположенные на
более «низких» уровнях.
Уровень contentPane должен быть родительским для размещения л ю
бого компонента. Для доступа к данному уровню используется метод
getContentPane().
Уровень glassPane является самым верхним. Для доступа к данному
уровню применяется метод getGlassPane(). Чтобы в приложении м о ж н о
было использовать уровень glassPane, для него следует вызвать метод
setGlassPane().
Например:
panel1.getContentPane().add(button1);
294
Лекция 27
Библиотека классов JDK. Основы построения интерфейса
пользователя на языке Java. Компоновки и элементы управления
К о м п о н е н т JTabbedPane реализует набор страниц, переключаемых по
щелчку пользователя на вкладках. Вкладки добавляются методами addTab
и insertTab. Вкладки нумеруются, начиная с 0.
Если количество вкладок равно нулю, то индекс текущей вкладки
равен -1.
На рис. 5 показан в н е ш н и й вид окна, содержащего панель вкладок
класса JTabbedPane.
1
_|п|х|
1Frame Title
Вкладка 1
Вкладка 2 | В к л а д к а З |
Рис. 5. Окно с компонентом JTabbedPane
Класс javax.swing.JScrollPane реализует компонент «прокручивае
мая область». Панель J S c r o l l P a n e состоит из:
• области просмотра (viewport) типа JViewport. Для добавления рамки во
круг области просмотра следует использовать метод setViewportBorder,
а для добавления рамки вокруг всей прокручиваемой области — ме¬
тод setBorder.;
• вертикальной и горизонтальной области прокрутки типа J S c r o l l B a r
(необязательная область);
• области заголовков строк и области заголовкоd столбцов (необяза
тельная область). Э т и области реализуются к а к объекты т и п а
JViewport, д л я к о т о р ы х в ы з в а н ы методы setRowHeaderView и
setColumnHeaderView;
• четырех угловых областей. П о умолчанию угловые области н е с о д е р д ^ т компонентов. Д л я того чтобы разместить в угловой области
компонент, следует использовать метод setCorner .
Чтобы изменить свойство области просмотра, ее следует получить,
вызвав метод getViewport. Н а п р и м е р , для задания цвета ф о н а нужно запи
сать: scrollPane.getViewport().setBackground(Color. red).
На рис. 6 показано расположение основных частей прокручиваемой
области J S c r o l l P a n e .
Контейнером для разделяемых панелей служит компонент JSplitPane.
Разделяемые плавающие панели имеют одну общую сторону — п о верти¬
кали или по горизонтали.
Следующий пример иллюстрирует создание окна, в котором п р и м е
няются разделяемые панели:
295
Курс
Введение в программирование
Рамка области просмотра
(viewportBorder)
J
S
c
Рис. 6. Структура прокручиваемой области J S c r o l l P a n e
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
p u b l i c c l a s s Framel extends JPanel {
J S p l i t P a n e j S p l i t P a n e l = new J S p l i t P a n e ( ) ; // Класс
// разделяемых панелей
J S c r o l l P a n e j S c r o l l P a n e 1 = new J S c r o l l P a n e ( ) ;
J S c r o l l P a n e j S c r o l l P a n e 2 = new J S c r o l l P a n e ( ) ;
JTextPane jTextPane1 = new JTextPane();
JTextPane jTextPane2 = new JTextPane();
p u b l i c Frame1() { t r y {
jbInit();
}
c a t c h ( E x c e p t i o n e) {
}}
public s t a t i c void main(String s [ ] ) {
JFrame frame = new JFrame("Панели");
frame.addWi ndowLi stener(new Wi ndowAdapter() {
publ i c vo i d wi ndowClos i ng(Wi ndowEvent e) {
System.exi t ( 0 ) ;
296
} });
r
o
l
l
B
a
r
s
Лекция 27
Библиотека классов JDK. Основы построения интерфейса
пользователя на языке Java. Компоновки и элементы управления
frame. setContentPane(new Frame1());
frame.pack();
frame.setVisible(true);
}
p r i v a t e v o i d j b I n i t ( ) throws Exception {
// Определение ориентации разделяемых панелей
jSplitPanel.setOrientation(JSplitPane.VERTICAL_SPLIT);
// Размещение левого и правого компонента
// на разделяемой панели
jSplitPanel.setLeftComponent(jScrollPane1);
jSplitPanel.setRightComponent(jScrollPane2);
// Отображение кнопок сворачивания и разворачивания
// сторон разделяемой панели
j SplitPane1.setOneTouchExpandable(true);
// Задание размера панелей
j S c r o l l P a n e 1 . s e t P r e f e r r e d S i z e ( n e w Dimension(300, 6 0 ) ) ;
j S c r o l l P a n e 2 . s e t P r e f e r r e d S i z e ( n e w Dimension(300, 6 0 ) ) ;
// Добавление разделяемой панели к окну формы
this.add(jSplitPane1, null);
// Добавление компонентов в контейнеры
// типа J S c r o l l P a n e
j Sc r o l l P a n e 1 . g e t V i e w p o r t ( ) . a d d ( j T e x t P a n e 1 , n u l l ) ;
jScrollPane2.getViewport().add(jTextPane2, n u l l ) ;
}
}
Кнопки
К н о п к и могут располагаться в контейнере как отдельно, так и в группе.
П а к е т java.awt содержит следующие классы к н о п о к и групп:
• Button — к о м а н д н а я к н о п к а .
• Checkbox — ф л а ж о к или р а д и о к н о п к а (переключатель).
• CheckboxGroup — группа к н о п о к .
П а к е т облегченных swing-компонентов т а к ж е предоставляет н е
с к о л ь к о классов к н о п о к и групп, включая следующие классы:
• JButton — к н о п к а .
• JRadioButton — р а д и о к н о п к а .
• JToggleButton — к н о п к а - п е р е к л ю ч а т е л ь .
• JCheckBox — ф л а ж о к .
• ButtonGroup — группа к н о п о к .
Н а к н о п к а х и з пакета javax. swing п о м и м о метки может т а к ж е отоб
ражаться и пиктограмма.
297
Курс
Введение в программирование
Класс Button позволяет создавать объекты «командные кнопки». При
нажатии на кнопку J V M инициирует событие действия actionPerformed.
Наряду с данным семантическим событием, инициируется ряд простых со¬
бытий, таких как mouseClicked.
Класс Button предоставляет ряд методов, включая следующие:
• AddActionListener — регистрирует блок прослушивания для события
действия от командной к н о п к и ;
• GetActionCommand — возвращает и м я команды, и н и ц и и р о в а в ш е й с о
бытие действия, или метку к н о п к и , если и м я команды равно null
(значение по умолчанию);
• GetLabel — возвращает метку командной к н о п к и или null для непо¬
меченной командной к н о п к и ;
• SetLabel — изменяет метку командной к н о п к и .
Класс Checkbox позволяет создавать к о м п о н е н т ы к н о п к и двух типов,
называемые флажками и радиокнопками. Такой компонент может иметь
два состояния: включено (true) и выключено ( f a l s e ) . К а ж д ы й щелчок на
компоненте изменяет его состояние на обратное.
Несколько переключателей могут быть объединены в группу, ис¬
пользуя компонент CheckboxGroup, я в л я ю щ и й с я контейнером. Такая груп
па называется группой радиокнопок. Только один компонент группы м о
жет одновременно иметь состояние «включен».
Д л я о б р а б о т к и с о б ы т и й от к н о п к и используется и н т е р ф е й с
ItemListener. Этот интерфейс определяет всего один обработчик события
— метод itemStateChanged (ItemEvent e).
Класс ItemEvent содержит метод getStateChange, п о з в о л я ю щ и й опре
делить состояние к н о п к и . Метод может возвращать одно из двух возмож¬
ных значений:
• ItemEvent.SELECTED;
• ItemEvent.DESELECTED.
Например:
// Определение состо ни кнопки
v o i d itemStateChanged(ItemEvent e) {
i f (e.getStateChange() == ItemEvent.SELECTED)
{ // Кнопка находится во включенном состоянии
}
}
Д л я д о б а в л е н и я к н о п к и в группу д л я н е е следует в ы з в а т ь метод
setCheckboxGroup,
указав в качестве параметра объект
типа
CheckboxGroup.
298
Лекция 27
Библиотека классов JDK. Основы построения интерфейса
пользователя на языке Java. Компоновки и элементы управления
Следующий листинг иллюстрирует создание флажков и группы ра¬
диокнопок:
import j a v a . a p p l e t . A p p l e t ;
import java.awt.*;
p u b l i c c l a s s MyApplet extends A p p l e t {
Panel panel1 = new P a n e l ( ) ;
GridLayout gridLayout1 = new G r i d L a y o u t ( ) ;
// Создание новой кнопки:
Checkbox checkbox1 = new Checkbox();
Checkbox checkbox2 = new Checkbox();
GridLayout g r i d L a y o u t 2 = new G r i d L a y o u t ( ) ;
Panel panel2 = new P a n e l ( ) ;
// Создание группы кнопок:
CheckboxGroup checkboxGroup1 = new CheckboxGroup();
Checkbox checkbox4 = new Checkbox();
Checkbox checkbox5 = new Checkbox();
Checkbox checkbox6 = new Checkbox();
FlowLayout FlowLayout1 = new FlowLayout();
p u b l i c MyApplet() {
try {
jbInit();
} c a t c h ( E x c e p t i o n e) { }
}
public s t a t i c void main(String[] args) {
MyApplet myApplet1 = new MyApplet(); }
p r i v a t e v o i d j b I n i t ( ) throws Exception {
setLayout(gridLayout2);
panel1.setLayout(gridLayout1);
checkbox1.setLabel("Флажок 1");
checkbox2.setLabel("Флажок 2");
c h e c k b o x 2 . s e t S t a t e ( t r u e ) ; // Состояние флажка // включен
gridLayout2.setRows(2);
panel2.setLayout(FlowLayout1);
// Добавление в группу трех кнопок:
checkbox4.setCheckboxGroup(checkboxGroup1);
checkbox4. setLabel("Радиокнопка 1");
c h e c k b o x 4 . s e t S t a t e ( t r u e ) ; // Состояние радиокнопки // включена
checkbox5.setCheckboxGroup(checkboxGroup1);
checkbox5.setLabel(" Радиокнопка 2");
checkbox6.setCheckboxGroup(checkboxGroup1);
299
Курс
Введение в программирование
checkbox6.setLabel(" Радиокнопка 3");
// Добавление кнопок в контейнеры - панели
this.add(panel1, n u l l ) ;
panel1.add(checkbox1,
panel1.add(checkbox2,
this.add(panel2, n u l l ) ;
panel2.add(checkbox4,
panel2.add(checkbox5,
panel2.add(checkbox6,
null);
null);
null);
null);
null);
}
}
Этот
•
•
•
•
•
•
•
•
•
•
•
Классы кнопок пакета javax.swing наследуются от класса AbstractButton.
класс предоставляет ряд общих методов, включая следующие:
doClick — выполнение щелчка мыши на кнопке программным способом;
getText — возвращает метку к н о п к и ;
setText — устанавливает метку к н о п к и ;
i s S e l e c t e d — определяет состояние к н о п к и и возвращает true, если
переключаемая к н о п к а находится в состоянии «включена»;
s e t S e l e c t e d — устанавливает состояние к н о п к и ;
setMargin — устанавливает отступы между рамкой к н о п к и и меткой;
s e t I c o n — определяет пиктограмму, используемую по умолчанию.
Эта пиктограмма используется для состояния к н о п к и «нажатая» или
«недоступная» в том случае, если для этих состояний не указана иная
пиктограмма;
setPressedIcon — определяет пиктограмму для нажатого («pressed»)
состояния к н о п к и ;
s e t S e l e c t e d I c o n — устанавливает пиктограмму для выделенного
(«selected») состояния к н о п к и ;
s e t R o l l o v e r I c o n — устанавливает п и к т о г р а м м у д л я нажатого
(«rollover») состояния к н о п к и (одновременно могут быть нажаты не¬
сколько к н о п о к ) ;
s e t D i s a b l e d I c o n — устанавливает пиктограмму для недоступного с о
стояния к н о п к и .
Например:
ImageIcon ImageIcon1= new
ImageIcon("myicon.gif");
jButton1.setDisabledIcon(ImageIcon1);
• s e t D i s a b l e d S e l e c t e d I c o n — устанавливает пиктограмму недоступно¬
го для выделения состояния к н о п к и ;
300
Лекция 27
Библиотека классов JDK. Основы построения интерфейса
пользователя на языке Java. Компоновки и элементы управления
• setVerticalAlignment — определяет выравнивание по вертикали для пик
тограммы и метки, которое может указываться следующими значениями:
— SwingConstants.CENTER (по умолчанию);
— SwingConstants.TOP;
— SwingConstants.BOTTOM;
• setHorizontalAlignment — определяет выравнивание по горизонтали
для пиктограммы и метки, которое может указываться следующими
значениями:
— SwingConstants.RIGHT (по умолчанию);
— SwingConstants.LEFT;
— SwingConstants.CENTER;
— SwingConstants.LEADING;
— SwingConstants.TRAILING;
• setVerticalTextPosition — определяет п о з и ц и ю текста по вертикали
относительно пиктограммы, которая может указываться следующи
ми значениями:
— SwingConstants.CENTER (по умолчанию);
— SwingConstants.TOP;
— SwingConstants.BOTTOM;
• setHorizontalTextPosition — определяет п о з и ц и ю текста по гори
зонтали относительно пиктограммы, которая может указываться
следующими значениями:
— SwingConstants.RIGHT (по умолчанию);
— SwingConstants.LEFT;
— SwingConstants.CENTER;
— SwingConstants.LEADING;
— SwingConstants.TRAILING.
• setActionCommand — задает команду действия для к н о п к и ;
• getActionCommand — возвращает строку, которая содержит команду
действия, установленную для д а н н о й к н о п к и ;
• setMnemonic — определяет код символа, используемого как ключ-ак
селератор (ALT+данный символ).
Например:
jButton1.setMnemonic(KeyEvent.VK_A);
Д л я того ч т о б ы о п р е д е л и т ь в методе обработки с о б ы т и я
itemStateChanged(ItemEvent e), какой к н о п к о й было и н и ц и и р о в а н о дан¬
н о е событие, следует использовать метод getItemSelectable.
Для того чтобы определить, является ли к н о п к а , и н и ц и и р о в а в ш а я
событие, выделенной (находящейся в состоянии «включена» или «нажа
та»), следует использовать метод getStateChange.
301
Курс
Введение в программирование
Например:
if
( e . g e t I t e m S e l e c t a b l e ( ) ==
jCheckBox1 && e.getStateChange()==e.SELECTED) {
}
Класс JToggleButton предназначен для создания к н о п о к , имеющих
два состояния — «нажата» и «не нажата». К о м п о н е н т JToggleButton может
находится в зафиксированном нажатом состоянии (быть выделенным).
Этот класс является непосредственным суперклассом для классов
JCheckbox и JRadioButton.
Для того чтобы установить состояние к н о п к и , следует использовать
метод setSelected.
Например:
jToggleButton1.setSelected(true);
К н о п к и JToggleButton могут быть объединены в группу. Такую груп¬
пу следует п р е д в а р и т е л ь н о создать, используя к о м п о н е н т т и п а
javax. swing. ButtonGroup. Только одна из к н о п о к группы может одновре
м е н н о иметь нажатое состояние.
Текстовые компоненты
Текстовые компоненты предназначаются для ввода и отображения строк.
Библиотека J D K предоставляет следующие классы текстовых ком¬
понентов:
• java.awt.TextArea — текстовая область.
• j a v a . a w t . T e x t F i e l d — текстовое поле, называемое также полем ввода.
• j a v a x . s w i n g . J T e x t F i e l d — текстовое поле.
• javax.swing.JPasswordField — текстовое поле, предназначаемое для
ввода пароля.
• javax.swing.JTextArea — текстовая область.
• javax.swing.JEditorPane — панель редактора, позволяющая отобра
жать как текстовые, так и графические д а н н ы е , а также применять
различное форматирование текста.
• javax.swing.JTextPane — текстовая панель, позволяющая отображать
содержимое с использованием различных шрифтов.
Все текстовые к о м п о н е н т ы пакета java.awt наследуются от класса
TextComponent.
Все текстовые к о м п о н е н т ы пакета javax. swing наследуются от клас¬
са JTextComponent.
302
Лекция 27
Библиотека классов JDK. Основы построения интерфейса
пользователя на языке Java. Компоновки и элементы управления
Д л я отображения текста, который может быть изменен только п р о
граммным путем, служат компоненты. Label из пакета j ava. awt и J L a b e l из
пакета javax.swing. К о м п о н е н т J L a b e l также м о ж н о использовать и для
отображения рисунков.
Б о л ь ш и н с т в о н а з в а н и й методов, предоставляемых
классами
TextComponent и JTextComponent для работы с текстом, совпадают. Так, для
того чтобы получить строку, которая содержит весь текст, расположенный
в текстовом компоненте, можно использовать метод getText, а для получе
н и я позиции ввода — метод g e t C a r e t P o s i t i o n ; для определения, можно ли
редактировать текст, — метод i s E d i t a b l e , для выделения текста в указанном
диапазоне — метод s e l e c t , а для выделения всего текста — метод s e l e c t A l l .
П р и каждом изменении значения текстового компонента, включая
ввод каждого символа, происходит событие textValueChanged. П р и нажа
т и и на к л а в и ш у Enter д л я текстового п о л я и н и ц и и р у е т с я с о б ы т и е
a c t i o n P e r f o r m e d . Н о п р и п е р е м е щ е н и и фокуса ввода
событие
actionPerformed не происходит.
Класс T e x t F i e l d позволяет создавать однострочные текстовые поля,
используемые для ввода и редактирования одной строки текста. Этот
класс предоставляет ряд методов, включая следующие:
• A d d A c t i o n L i s t e n e r — регистрирует блок прослушивания для обработ
к и события действия компонента «текстовое поле».
• EchoCharIsSet — возвращает значение true в том случае, если ввод в
д а н н о е текстовое поле отображается н е к о т о р ы м э х о - с и м в о л о м ,
с к р ы в а ю щ и м действительное значение поля.
• GetColumns — возвращает размер данного текстового поля (количест¬
во символов).
• GetEchoChar — возвращает эхо-символ для данного текстового поля.
• SetEchoCharacter — устанавливает значение эхо-символа для д а н н о
го текстового поля. Любой вводимый пользователем символ будет
экранирован д а н н ы м эхо-символом.
• SetColumns — устанавливает размер текстового поля в символах.
• SetText — определяет новое значение текстового поля.
Хотя к о м п о н е н т ы пакета javax. swing и называются облегченными,
но о н и предоставляют значительно большие возможности, чем традици¬
о н н ы е текстовые к о м п о н е н т ы пакета java.awt.
Управление текстом, отображаемым в текстовом компоненте, опре
деляется интерфейсом Document. Этот интерфейс предназначен для опре
деления методов работы с текстом. И н т е р ф е й с Document реализован клас¬
сом AbstractDocument.
Текст в компоненте типа JTextComponent представляется ассоциируе
мой с ним текстовой моделью, определяющей как содержание, так и стиль.
303
Курс
Введение в программирование
Фактически, текстовый компонент предоставляет доступ к:
• модели, реализуемой на основе интерфейса Document и представляю¬
щей собой содержание документа;
• области просмотра текстового компонента;
• набору команд редактирования,
предусмотренного для текстового
компонента;
• таблице ключей акселераторов, связанных с таблицей именованных
действий.
Классы DefaultEditorKit и StyledEditorKit описывают набор и м е н о
ванных действий, которые м о ж н о использовать для создания на основе
текстового компонента редактора текста.
В классе DefaultEditorKit определен набор предоставляемых тексто¬
вому компоненту действий, таких как перемещение курсора, выделение
или вставка текста.
Н а п р и м е р , для создания пункта меню, выполняющего форматиро
вание выделенного диапазона текста, и изменения размера шрифта на
14p, следует записать:
menu.add(new S t y l e d E d i t o r K i t . F o n t S i z e A c t i o n (
"Имя пункта меню", 14));
Константы класса D e f a u l t E d i t o r K i t описывают набор именованных
действий, включая следующие:
• BackwardAction — перемещение позиции ввода на одну позицию назад.
• BeepAction — подача звукового сигнала.
• BeginAction — перемещение п о з и ц и и ввода на начало документа.
• BeginParagraphAction — перемещение позиции ввода в начало абзаца.
• BeginLineAction — перемещение п о з и ц и и ввода в начало строки.
• BeginWordAction — перемещение позиции ввода на начало текущего
слова.
• CutAction — вырезание выделенного диапазона текста и п о м е щ е н и е
его в буфер обмена.
• CopyAction — копирование выделенного диапазона текста в буфер
обмена.
• DeleteNextCharAction — удаление следующего символа.
• DownAction — перемещение п о з и ц и и ввода на один ряд вниз.
• DeletePrevCharAction — удаление предыдущего символа.
• EndAction — перемещение п о з и ц и и ввода в конец документа.
• EndLineAction — перемещение п о з и ц и и ввода в к о н е ц строки.
• EndParagraphAction — перемещение п о з и ц и и ввода в конец абзаца.
• EndWordAction — перемещение позиции ввода на конец текущего слова.
• ForwardAction — перемещение позиции ввода на один символ вперед.
304
Лекция 27
Библиотека классов JDK. Основы построения интерфейса
пользователя на языке Java. Компоновки и элементы управления
• InsertBreakAction — вставка в документ символа к о н ц а абзаца.
• InsertTabAction — вставка символа табуляции.
• NextWordAction — перемещение п о з и ц и и ввода на начало следующе¬
го слова.
• PageDownAction — перемещение позиции ввода на одну страницу вниз.
• PageUpAction — перемещение п о з и ц и и ввода на одну страницу вверх.
• PasteAction — вставка содержимого буфера обмена вместо выделен¬
ного диапазона текста или перед текущей позицией ввода.
• PreviousWordAction — перемещение п о з и ц и и ввода на начало преды¬
дущего слова.
• ReadOnlyAction — перевод редактора в режим «только чтение».
• SelectAllAction — выделение всего документа.
• SelectionBackwardAction — р а с ш и р е н и е области выделения на одну
п о з и ц и ю назад (влево).
• SelectionBeginAction — р а с ш и р е н и е области выделения до начала
документа.
• SelectionBeginLineAction — р а с ш и р е н и е области выделения до нача¬
ла текущей строки.
• SelectionBeginParagraphAction — р а с ш и р е н и е области выделения до
начала текущего абзаца.
• SelectionBeginWordAction — р а с ш и р е н и е области выделения до нача¬
ла текущего слова.
• SelectionDownAction — р а с ш и р е н и е области выделения на одну по¬
з и ц и ю вниз.
• SelectionEndAction — р а с ш и р е н и е области выделения до конца до¬
кумента.
• SelectionEndLineAction — р а с ш и р е н и е области выделения до конца
строки.
• SelectionEndParagraphAction — р а с ш и р е н и е области выделения до
конца абзаца.
• SelectionEndWordAction — р а с ш и р е н и е области выделения до конца
текущего слова.
• SelectionForwardAction — р а с ш и р е н и е области выделения на один
символ вперед (вправо).
• SelectionNextWordAction — р а с ш и р е н и е области выделения до нача¬
ла следующего слова.
• SelectionPreviousWordAction — р а с ш и р е н и е области выделения до
начала предыдущего слова.
• SelectionUpAction — р а с ш и р е н и е области выделения на одну пози¬
ц и ю вверх.
• SelectLineAction — выделение строки, в которой расположена п о з и
ц и я ввода.
305
Курс
Введение в программирование
• S e l e c t P a r a g r a p h A c t i o n — выделение абзаца, в котором расположена
позиция ввода.
• SelectWordAction — выделение слова, в котором расположена п о з и
ц и я ввода.
• UpAction — перемещение п о з и ц и и ввода на одну п о з и ц и ю вниз.
• W r i t a b l e A c t i o n — перевод редактора в режим редактирования текста.
Для того чтобы добавить в документ строку в отформатированном ви
де, можно использовать метод i n s e r t S t r i n g класса DefaultStyledDocument.
Этот класс является подклассом класса Abst ractDocument и реализует интер
ф е й с ы Document и StyledDocument.
Интерфейс StyledDocument определяет методы для работы со стилем
документа. Так, для назначения диапазону текста набора атрибутов стиля
м о ж н о использовать метод s e t C h a r a c t e r - A t t r i b u t e s , а для определения
используемого стиля или ш р и ф р а — методы g e t S t y l e и getFont.
Атрибуты стиля определяются интерфейсом A t t r i b u t e S e t . Этот и н
терфейс реализован классом S i m p l e A t t r i b u t e S e t .
Для создания набора атрибутов стиля следует создать переменную
типа S i m p l e A t t r i b u t e S e t и установить атрибуты стиля, используя методы
класса Например:
S i m p l e A t t r i b u t e S e t a t t r S t = new S i m p l e A t t r i b u t e S e t ( ) ;
StyleConstants.setBold(attrSt, true);
S t y l e C o n s t a n t s . s e t F o n t S i z e ( a t t r S t , 12);
StyleConstants.setForeground(attrSt,
Color.red);
П р и добавлении строки в текстовый документ вызовом метода
i n s e r t S t r i n g класса Default-StyledDocument один из параметров ссылается
на набор аттрибутов.
Фактически набор атрибутов стиля накладывается на диапазон тек
ста. Если текстовый компонент содержит текст с различным форматиро¬
ванием, то на каждый отдельный диапазон текста должен быть «наложен»
свой набор атрибутов стиля.
Для создания таблицы ключей акселераторов, используемых для
текстового компонента, следует:
1.
Создать объект класса Keymap для компонента класса JTextPane.
Например:
JTextPane textPane;
Keymap keymap = textPane.addKeymap("MyKeymap",
textPane.getKeymap());
306
Лекция 27
2.
Библиотека классов JDK. Основы построения интерфейса
пользователя на языке Java. Компоновки и элементы управления
Создать объект класса A c t i o n и установить д л я него действие, о п и
с а н н о е в классе D e f a u l t E d i t o r K i t .
Например:
Action action = getActionByName(DefaultEditorKit.downAction);
3.
Создать объект класса KeySt roke и установить для него значение клю¬
ча акселератора.
Например:
KeyStroke key =
4.
KeyStroke.getKeyStroke(KeyEvent.VK_N,
Event.CTRL_MASK);
Установить связь между созданным действием и ключем акселератором.
Например:
keymap.addActionForKeyStroke(key,
action);
Класс StyleConstants предоставляет набор методов, позволяю
щ и х определять и л и устанавливать значения для атрибутов ф о р м а т и
рования.
Н а б о р атрибутов ф о р м а т и р о в а н и я может быть создан к а к объект од¬
ного из следующих классов:
• SimpleAttributeSet.
• A t t r ibuteSet.
• MutableAttr ibuteSet.
Например:
S i m p l e A t t r i b u t e S e t [ ] a t t r s = new
S i m p l e A t t r i b u t e S e t [ s t r i n g F o r P a n e . length +1];
// Создание набора атрибутов:
a t t r s [ 0 ] = new S i m p l e A t t r i b u t e S e t ( ) ;
StyleConstants. s e t F o n t F a m i l y ( a t t r s [ 0 ] , " S a n s S e r i f " ) ;
// Установка значения атрибута
S t y l e C o n s t a n t s . s e t F o n t S i z e ( a t t r s [ 0 ] , 12);
a t t r s [ 1 ] = new S i m p l e A t t r i b u t e S e t ( a t t r s [ 0 ] ) ;
S t y l e C o n s t a n t s . s e t F o n t S i z e ( a t t r s [ 1 ] , 14);
StyleConstants.setBold(attrs[1], true);
// Добавление строки в документ с заданным набором
// атрибутов (defaultStyleDocument1 переменна
// класса, наследуемого от DefaultStyleDocument)
defaultStyleDocument1.insertString(
307
Курс
Введение в программирование
defaultStyleDocument1.length,
s t r i n g 1,
attrs[1]);
Списки
С п и с к и позволяют отображать группу элементов в один столбец,
предоставляя пользователю возможность выбора элемента.
Библиотека J D K содержит ряд классов списков, включая следующие:
• java.awt.List — список.
• java.awt.Choice — ниспадающий список.
• javax.swing.JList — список.
• javax.swing.JComboBox — ниспадающий список.
П р и выделении элемента в списке или в ниспадающем списке (или
отмене выделения) инициируется событие itemStateChanged. В метод об
работки этого события передается объект типа ItemEvent. Используя свой
ство SELECTED для объекта типа ItemEvent, м о ж н о определить, выделен ли
элемент списка. Интерфейс ItemListener описывает метод обработки с о
бытия itemStateChanged.
П р и д в о й н о м щелчке м ы ш ь ю на элементе списка (или нажатии кла¬
в и ш и Enter при выделенном элементе списка) для компонента типа L i s t ,
J L i s t или JComboBox инициируется событие actionPerformed. В метод обра
ботки этого события передается объект типа ActionEvent. Интерфейс
A c t i o n L i s t e n e r описывает метод обработки события actionPerformed.
З а п о л н е н и е с п и с к о в м о ж н о в ы п о л н я т ь в обработчике события
фрейма windowOpened. Добавление элементов в список L i s t и Choice в ы
полняется методом add.
Например:
L i s t l i s t 1 = new L i s t ( 4 , f a l s e ) ; // Создание списка
// с 4 видимыми строками и с запретом множественного выбора
list1.add("Строка 1"); // Добавление элементов в список
^ ^ ^ ( " С т р о к а 2");
^ ^ ^ ( " С т р о к а 3");
list1.add("Строка 4");
list1.add("Строка 5");
list1.add("Строка 6");
add(list1);
// Добавление списка в текущий контейнер
С п и с о к J L i s t позволяет выделять один или несколько элементов.
Содержание списка представляется моделью ListModel. Доступ к элемен
там списка реализуется с использованием модели. Для заполнения с п и с
ка используется метод s e t L i s t D a t a .
308
Библиотека классов JDK. Основы построения интерфейса
пользователя на языке Java. Компоновки и элементы управления
Лекция 27
С п и с о к J L i s t непосредственно н е поддерживает прокрутку списка.
Реализовать скроллинг м о ж н о двумя способами:
• Поместить с п и с о к в контейнер типа J S c r o l l P a n e .
Например:
JScrollPane
s c r o l l P a n e = new J S c r o l l P a n e ( j L i s t 1 ) ;
• Установить для объекта типа J S c r o l l P a n e на уровне Viewport
(getViewport) в качестве к о м п о н е н т а области просмотра (setView)
объект т и п а J L i s t .
Например:
J S c r o l l P a n e s c r o l l P a n e = new J S c r o l l P a n e ( ) ;
scrollPane.getViewport().(j List1);
Например:
S t r i n g [ ] data = {"один", "два", "три"};
// Массив строк
J L i s t j L i s t 1 = new J L i s t ( d a t a ) ;
// Создание списка,
// содержащего массив строк
// Доступ к элементам списка через модель
f o r ( i n t i = 0; i < j L i s t 1 . g e t M o d e l ( ) . g e t S i z e ( ) ;
{
System.out.println(jList1.getModel().getElementAt(i));
}
// Заполнение списка данными, представляемыми классом V e c t o r
J L i s t j L i s t 1 = new J L i s t ( ) ;
V e c t o r superClasses = new V e c t o r ( ) ;
Class rootClass = javax.swing.JList.class;
// Создание объекта
// типа C l a s s
f o r ( C l a s s c l s = rootClass; c l s != n u l l ;
cls =
cls.getSuperclass())
{ // Получение всех подклассов
superClasses.addElement(cls); }
j L i s t 1 . s e t L i s t D a t a ( s u p e r C l a s s e s ) ; // Заполнение компонента j L i s t 1
// списком всех его подклассов
// Добавление элементов в список, хранимый в объекте типа V e c t o r
superClasses.addElement(new S t r i n g ( " 1 2 3 4 5 " ) ) ;
// Выделение элементов списка:
j L i s t 1 . s e t S e l e c t e d I n d e x ( 1 ) ; // Выделение второго элемента списка
jList1.getSelectedValue();
// Возвращает строку, отображаемую
//во втором элементе списка
309
Курс
Введение в программирование
Глава 6. Программирование для Интернет
Лекция 28. Серверные приложения
В з а и м о д е й с т в и е по п р о т о к о л у TCP/IP
Протокол TCP/IP (Transmission Control Protocol/Internet Protocol)
предназначен для установления соединения между двумя компьютерами
в сети, обычно называемыми клиентом и сервером. Протокол T C P / I P оп¬
ределяет IP-адрес и номер порта.
IP—адрес задает и м я компьютера в сети. IP-адрес указывается или
как числовой идентификатор компьютера, или, при использовании сер¬
вера D N S , — как символьный псевдоним числового идентификатора.
Локальный компьютер всегда адресуется как 127.0.0.1 или l o c a l h o s t .
П р и работе в Интернете все используемые IP-адреса уникальны. П о
этому для задания своему П К некоторого IP-адреса следует получить этот
адрес у провайдера.
П р и работе только в локальной сети предприятия м о ж н о самостоя
тельно установить различные IP-адреса для каждого П К . Например:
192.168.0.2; 192.168.0.3; 192.168.0.4 и т.д.
Номер порта — это значение, однозначно идентифицирующее н е к о
торый логический порт приложения, через который м о ж н о получать и
посылать данные.
С о з д а н и е с е р в е р н ы х п р и л о ж е н и й на С + + в с р е д е
п р о е к т и р о в а н и я VisualStudio .NET
CGI и ISAPI приложения
Д а н н ы е , отображаемые web-браузером, представляют собой H T M L страницу.
П о H T T P - з а п р о с у web-браузер посылает на web-сервер и н ф о р м а
цию, содержащую URL-адрес документа, тип запроса и значения параме
тров. URL-адрес может указывать как простую H T M L - с т р а н и ц у и п р и л о
ж е н и е , выполняемое на web-сервере. Такое приложение иногда называет
ся серверным приложением.
К серверным п р и л о ж е н и я м относятся CGI-приложения и ISAPI-при
ложения.
310
Лекция 28
Серверные приложения
В отличии от C G I - п р и л о ж е н и й , выполняемых в отдельном процес
се, ISAPI-приложения реализуются к а к DLL-библиотеки.
Результатом в ы п о л н е н и я C G I или ISAPI-приложения чаще всего я в
ляется динамически сформированная H T M L - с т р а н и ц а .
HTTP-запросы
Н Т Т Р - з а п р о с формируется в соответствии с протоколом H T T P
(Hypertext Transfer Protocol). В HTTP-запросе указывается G E T - или POSTметод передачи данных. П р и вводе URL-адреса в поле адреса web-браузера
или выполнении формы (пользователь щелкнул по кнопке типа S U B M I T )
формируется HTTP-запрос. Если форма содержала данные, то они будут до
бавлены в конец строки с URL-адресом (при использовании метода G E T ) .
Соответственно, такой способ накладывает ограничение на размер переда¬
ваемых параметров. Если при выполнении формы атрибут M E T O D уста¬
новлен равным POST, то используется POST-метод, при котором сначала на
сервер посылается строка POST-запроса и HTTP-заголовки запроса, а затем
пустая строка и строка, содержащая передаваемые параметры.
ISAPI-приложение может использоваться к а к для ф о р м и р о в а н и я
динамической H T M L - с т р а н и ц ы , так и для обработки параметров, полу¬
чаемых от ф о р м ы .
В строке адреса web-браузера может быть указан только непосредст
венно URL-адрес выполняемого серверного приложения. В этом случае
для обработки такого запроса используется команда, определяемая мак
росом DEFAULT_PARSE_COMMAND.
Если после URL-адреса за вопросительным знаком следует идентифи
катор команды, то для обработки данного HTTP-запроса следует использо
вать функцию, сопоставленную данной команде макросом ON_PARSE_COMMAND.
Н а п р и м е р , для обработки строки
http://LOCALHOST/MyISAPI_1.dll?Myfunc?st ring1&123
ISAPI-приложение будет вызывать ф у н к ц и ю Myfunc и передавать ей
в качестве параметров три значения: первым параметром всегда будет
указатель на HTTP-контекст, а далее будут следовать параметры, указан
н ы е в HTTP-запросе. В д а н н о м примере это два параметра: s t r i n g 1 и 123.
Между собой параметры разделяются символом &.
Создание ISAPI-приложения
Для того чтобы создать ISAPI-приложение, иногда также называе
мое ISAPI-расширением,
следует:
311
Курс
Введение в программирование
1.
2.
создать новый проект;
в диалоге New Project выбрать шаблон создаваемого документа M F C
ISAPI Extension D l l ;
3.
перейти на страницу Object Setting мастера ISAPI Extension Wizard и
установить флажок Generate a server extension object.
В результате выполненных действий мастер ISAPI Extension Wizard
сформирует шаблон ISAPI-приложения. В заголовочном файле StdAfx. h,
который добавляется в шаблон любого приложения, использующего
MFC-библиотеку, указана строка #include < a f x i s a p i . h> — о н а в ы п о л н я
ет подключение файла a f x i s a p i . h, который объявляет следующие классы,
поддерживающие работу с H T T P - з а п р о с а м и :
class
class
class
class
class
class
ChtmlStream.
ChttpServerContext.
ChttpServer.
ChttpFilterContext.
ChttpFilter.
CHttpArgList.
ISAPI-приложение создается к а к DLL-библиотека. Класс, в ы п о л н я
ю щ и й обработку H T T P - з а п р о с а и ф о р м и р у ю щ и й динамическую H T M L страницу, наследуется от класса CHttpServer.
В следующем листинге приведен к о д заголовочного файла и файла
реализации класса, наследуемого от CHttpServer. В автоматически с ф о р
м и р о в а н н ы й код ISAPI-приложения внесены изменения, которые добав
ляют в создаваемую H T M L - с т р а н и ц у две строки текста и форму, содержа
щую элемент управления.
Листинг:
// Заголовочный файл MyISAPI_1.h
#pragma once
#include "resource.h"
c l a s s CMyISAPI_1Extension : p u b l i c
CHttpServer
{
public:
CMyISAPI_1Extension();
// Конструктор
~CMyISAPI_1Extension();
public:
v i r t u a l BOOL GetExtensionVersion(HSE_VERSION_INFO* pVer);
v i r t u a l BOOL TerminateExtension(DWORD dwFlags);
v o i d D e f a u l t ( C H t t p S e r v e r C o n t e x t * pCtxt);
DECLARE_PARSE_MAP()
312
Лекция 28
Серверные приложения
};
// Файл реализации MyISAPI_1.cpp
#include " s t d a f x . h "
#include "MyISAPI_1.h"
CWinApp theApp;
// Объект «приложение»
BEGIN_PARSE_MAP(CMyISAPI_1Extension, CHttpServer)
// Таблица
// обработки команды
// TODO: место дл определени ON_PARSE_COMMAND() и
// ON_PARSE_COMMAND_PARAMS()
ON_PARSE_COMMAND(Default, CMyISAPI_1Extension, ITS_EMPTY)
DEFAULT_PARSE_COMMAND(Default,
CMyISAPI_1Extension)
END_PARSE_MAP(CMyISAPI_1Extension)
CMyISAPI_1Extension t h e E x t e n s i o n ;
// Только один объект
//ISAPI-расширение класса,
// наследуемого от CHttpServer
CMyISAPI_1Extension::CMyISAPI_1Extension(){
}
// Конструктор
CMyISAPI_1Extension::~CMyISAPI_1Extension() {
}
BOOL CMyISAPI_1Extension::GetExtensionVersion(HSE_VERSION_INFO*
pVer)
{
// Вызов метода базового класса
CHttpServer::GetExtensionVersion(pVer);
// Загрузка строки описания
TCHAR sz[HSE_MAX_EXT_DLL_NAME_LEN+1];
ISAPIVERIFY(::LoadString(AfxGetResourceHandle(), // Макро - если
IDS_SERVER, sz, HSE_MAX_EXT_DLL_NAME_LEN)); // 0,то завершение
_tcscpy(pVer->lpszExtensionDesc, s z ) ;
return TRUE;
}
BOOL CMyISAPI_1Extension::TerminateExtension(DWORD
dwFlags)
{ // Метод класса CHttpServer - позволяет выполнить завершение
// потоков и работы ISAPI-расширения
return TRUE;
}
// CMyISAPI_1Extension : методы обработчики
// Код формируемой HTML-страницы записывается методом D e f a u l t
// в поток вывода
v o i d CMyISAPI_1Extension::Default(CHttpServerContext* p C t x t )
{
StartContent(pCtxt);
WriteTitle(pCtxt);
// Начало HTML-страницы
// Формирование значения тега TITLE
// _T - дл Unocode конвертируетс в L
*pCtxt << _ T ( " HTML-page from " ) ;
// Первая строка
//HTML- страницы
313
Курс
Введение в программирование
*pCtxt << _ T ( " I S A P I - a p p l i c a t i o n " ) ;
// Формирование строки HTML-документа для отображения формы
*pCtxt << _T("<FORM> <INPUT TYPE='text' SISE=30 </FORM>");
EndContent(pCtxt);
// Завершение HTML-страницы
}
// Следующие строки вставл ютс мастером
// ISAPI Extension Wizard
// только на тот случай, если ISAPI-расширение не будет
// использовать MFC- бибиотеку.
// В противном случае эти строки можно удалить
/****
s t a t i c HINSTANCE g_hInstance;
HINSTANCE AFXISAPI AfxGetResourceHandle()
{ return g_hInstance;}
BOOL WINAPI DllMain(HINSTANCE hInst, ULONG ulReason,
// Точка
LPVOID lpReserved)
// входа в DLL-модуль
{
i f (ulReason == DLL_PROCESS_ATTACH)
{
g_hInstance = hInst; }
return TRUE;
}
****/
Каждый запрос обрабатывается некоторой функцией. П р и вызове
т а к о й ф у н к ц и и , в качестве параметра ей передается объект т и п а
CHttpServerContext. Д л я каждой такой ф у н к ц и и должен быть указан вход
в таблице обработки команд.
Таблица
описания
команд
Для таблицы описания команд в M F C - б и б л и о т е к у включены пять
следующих макросов:
• BEGIN_PARSE_MAP — определяет начало таблицы описания команд и
указывает класс ф у н к ц и й членов и базовый класс.
• END_PARSE_MAP — определяет конец таблицы описания команд.
• ON_PARSE_COMMAND — идентифицирует команду и указывает соответст¬
вующую ей ф у н к ц и ю .
• ON_PARSE_COMMAND_PARAMS — определяет с п и с о к параметров обрабаты
ваемой команды. Этот макрос должен следовать непосредственно за
макросом ON_PARSE_COMMAND.
• DEFAULT_PARSE_COMMAND — определяет команду, используемую в том
случае, если нет явного указания выполняемой команды.
314
Лекция 28
Серверные приложения
Макрос ON_PARSE_COMMAND используется при определении команды
для объекта класса CHttpServer (или наследуемого от него), поступающей
от клиента, и имеет следующее описание:
ON_PARSE_COMMAND(FnName, mapClass, Args)
Параметры:
FnName — и м я ф у н к ц и и члена класса, а также и и м я команды.
mapClass — и м я класса указанной ф у н к ц и и .
Args — указывает тип списка параметров и может принимать следую¬
щ и е значения:
ITS_EMPTY
— параметров нет;
ITS_PSTR
— указатель на строку;
ITS_RAW
— д а н н ы е , предварительно не обрабатываемые. Ис¬
пользуется в том случае, если список параметров
H T T P - з а п р о с а может иметь различное число па¬
раметров;
ITS_I2
— значение типа short
ITS_I4
— значение типа long
ITS_R4
— значение типа float
ITS_R8
— значение типа double
ITS_I8
— значение типа 64-битовое integer
ITS_ARGLIST
— указатель на объект типа CHttpArgList.
Например:
BEGIN PARSE_MAP(CDerivedClass,
CHttpServer)
DEFAULT_PARSE_COMMAND(Myfunc, CDerivedClass)
// Дл
запроса типа
// http://LOCALSERVER/MyISAPI_1.dll?Myfunc&string1&135
ON_PARSE_COMMAND(Myfunc,
// Имя функции
CDerivedClass,
// Имя класса
ITS_PSTR ITS_I2)
// Список из двух параметров:
// указатель на строку, значение типа s h o r t
ON_PARSE_COMMAND_PARAMS("string
// Дл
запроса с трем
integer=42")
параметрами
ON_PARSE_COMMAND(Myfunc2,
CDerivedClass,
ITS_PSTR ITS_I2 ITS_PSTR)
315
Курс
Введение в программирование
ON_PARSE_COMMAND_PARAMS("string integer string2='Default value'")
DEFAULT_PARSE_COMMAND(Myfunc3, C D e r i v e d C l a s s )
ON_PARSE_COMMAND(Myfunc3, CDe r i v e d C l a s s ,
ITS_RAW)
// Различное число параметров
END_PARSE_MAP(CDerivedClass)
// Функции, выполн емые дл
обработки команд
void Myfunc(CHttpServerContext* pCtxt, LPTSTR pszName, i n t nNumber)
{
}
// Первый параметр стандартен дл
всех функций,
// обрабатывающих команды, тип второго и третьего
// параметра был указан в макросе ON_PARSE_COMMAND
v o i d Myfunc2(CHttpServerContext* pCtxt, LPTSTR
i n t nNumber, LPTSTR
{
pszName,
pszTitle)
}
v o i d CDerivedClass::Myfunc3(
// Используется тип параметров
// ITS_RAW
CHttpServerContext* pCtxt,
v o i d * pVoid,
// pVoid - указатель на передаваемые данные
DWORD dwBytes) // dwBytes - количество переданных байтов данных
{
}
Разбор
списка
параметров
Д л я з а п р о с о в т и п а http://LOCALSERVER/MyISAPI_2.dll?Myfunc&s1=
10&s2=35&c1=y
можно использовать макрос с типом параметров
ITS_ARGLIST:
ON_PARSE_COMMAND(Myfunc, CMyHttpServer,
ITS_ARGLIST).
Далее для разбора такого с п и с к а параметров используется класс
CHttpA r g L i s t .
К л а с с C H t t p A r g L i s t п р е д с т а в л я е т с о б о й м а с с и в структур т и п а
CHttpArg.
П р и этом д а н н ы е доступны через объект CHttpArg.
П о л е CHttpArg::m_pstrValue содержит значение параметра, а поле
CHttpArg: :m_pstrArg — и м я параметра.
Например:
для строки http://localserver/my1.dll&Arg1=hockey&Arg2&Arg3=bee
надо реализовать разбор параметров п о следующей схеме.
316
r+nuts
Лекция 28
Серверные приложения
CHttpArgList
GetFirstArgO
GetNextArgQ
GetNextArgO
GetNextArgO
CHttpArg
• _ p s t r A r g = "Arg1"
• _ p s t rValue = "Hockey"
• _pstrRaw = "Arg1" = "Hockey"
CHttpArg
• _ p s t r A r g = "Arg2"
• _ p s t rValue
• _pstrRaw = "Arg2"
CHttpArg
• _ p s t r A r g = "Arg3"
• _ p s t rValue = "Beer + nuts"
• _pstrRaw = "Arg3 = Beer + nuts"
Выполнение ISAPI-приложения
Д л я в ы п о л н е н и я ISAPI-приложения соответствующую D L L - б и б л и
отеку следует поместить в каталог web-сервера. Таким сервером может
быть Internet Information Server и л и любой другой web-сервер.
Д л я просмотра сведений о виртуальных каталогах web-сервера на па
нели инструментов следует выбрать пиктограмму Administrative Tools и от
крыть диалог для администрирования web -сервера.
Д л я IIS сервера следует выбрать пиктограмму Internet Information
Services. Отображаемый далее диалог Internet Information Services (рис. 1)
позволяет получать и н ф о р м а ц и ю и настраивать ISS сервер.
Рис. 1. Диалог Internet Information Services
317
Курс
Введение в программирование
Для того, чтобы получить информацию о расположении домашнего ка
талога ISS-сервера, следует на панели, расположенной слева, выделить эле
мент Default Web Site и выполнить команду контекстного меню Properties.
В диалоге Default Web Site Properties на странице Home Directory в п о
ле Local Path указано расположение домашнего каталога. Д л я того чтобы
из данного каталога можно было загружать как H T M L - ф а й л ы , так и D L L файлы, значение поля Executable Permissions должно быть установлено
р а в н ы м S c r i p t and Executables.
После размещения ISAPI-приложения в д о м а ш н е м каталоге webсервера, это приложение можно выполнить в web-броузере, указав соот
ветствующий URL-адрес.
П р и выполнении приложения на локальном компьютере в качестве
имени сервера указывается LOCALHOST.
Например: http://LOCALHOST/MyISAPI_1. d l l .
П р и размещении ISAPI-приложения на web -сервере и м я приложе
н и я можно изменить. Н а р и с . 2 приведен результат выполнения в webбраузере описанного выше ISAPI-приложения.
jajxj
| 3 Default MFC Web Server Extension - Microsoft I... [7
File
Edit
$*Back
Address
-
View
4
* 3
Favorites
@
1Й
lools
Help
| Q Search
http://LOCALH.05T/MyI5API_4.dll
Favorites
tf^Go
Ш»
| Links
J >
HTML-pagefromISAPI-application
|lSAPI -
приложение
'©J Done
Local intranet
Л
Рис. 2. Выполнение ISAPI-приложения в web -браузере
П р и первом в ы п о л н е н и я ISAPI-приложения сервер загружает дан
ную D L L . П р и всех последующих вызовах обращение происходит к уже
загруженной D L L .
Создание приложений, выполняемых
на W E B - с е р в е р е , в с р е д е п р о е к т и р о в а н и я DELPHI
Среда проектирования Delphi также позволяет создавать C G I и
ISAPI приложения.
318
Лекция 28
Серверные приложения
Создание CGI-приложения
Если WEB-броузер посылает в качестве запроса URL-адрес C G I приложения, то web-сервер запускает это приложение и передает ему па
раметры запроса через стандартный ввод. С ф о р м и р о в а н н а я в результате
выполнения C G I - п р и л о ж е н и я H T M L - с т р а н и ц а возвращается WEB-серверу через стандартный вывод.
Для того, чтобы создать C G I - п р и л о ж е н и е , запускаемое на сервере,
следует создать проект Web Server Application и в диалоге New Web Server
Application (рис. 3) выбрать тип серверного приложения (например, C G I
Stand-alone executable).
Рис. 3. Диалог New web Server Application
В результате будет создан проект, содержащий главный файл прило
ж е н и я и модуль Unit1:
{Главный файл приложения}
program P r o j e c t 1 ;
{$APPTYPE CONSOLE}
uses
WebBroker,
CGIApp,
Unit1 i n 'Unit1.pas' {WebModule1:
{$R *.RES}
begin
TWebModule};
Application.Initialize;
Application.CreateForm(TWebModule1, WebModule1);
Application.Run;
end.
{Модуль Unit1.pas}
u n i t Unit1;
interface
319
Курс
Введение в программирование
uses
S y s U t i l s , Classes, HTTPApp;
type
TWebModule1 = class(TWebModule)
private
{ Private declarations }
public
{ Public declarations }
end;
var
WebModule1: TWebModule1;
implementation
{$R *.DFM}
end.
Д л я того ч т о б ы создать код, ф о р м и р у ю щ и й H T M L - с т р а н и ц у , следу
ет создать объект типа TWebActionItem ( н а п р и м е р , WebActionItem1), а далее
создать для д а н н о г о объекта обработчик события действия OnAction.
П р и этом автоматически будет с ф о р м и р о в а н следующий код:
procedure TWebModule1.WebModule1WebActionItem1Action(
Sender: TObject;
Request: TWebRequest;
Response: TWebResponse;
var Handled: Boolean);
begin
end;
Код HTML-страницы
Response.
Например:
з а п и с ы в а е т с я в свойство Content объекта
//1.
Response.Content:='<I>Результат выполнения </I> '+
<P> <B> CGI- приложени </B></P>;
// 2.
var
aPage : TSt r i n g L i s t ;
i : integer;
begin
aPage:= T S t r i n g L i s t . C r e a t e ;
aPage.Add('Method = ' +Request.Method + '<BR>');
aPage.Add('URL = ' + Request.URL+ '<BR>');
aPage.Add('User Agent = ' + Request.UserAgent+ '<BR>');
aPage.Add('Remote Address = ' + Request.RemoteAddr+ '<BR>');
320
Лекция 28
Серверные приложения
aPage.Add('Remote Host = ' + request.RemoteHost+ '<BR>');
Response.Content := aPage.Text;
aPage.Free;
П о с л е р а з м е щ е н и я с о з д а н н о г о C G I - п р и л о ж е н и я в каталог W E B сервера, п р е д н а з н а ч е н н ы й д л я и с п о л н я е м ы х ф а й л о в , web -браузер м о
жет формировать запрос, указывая URL-адрес данного C G I - п р и л о
жения.
Разбор параметров
Для доступа к значению ф о р м ы из G E T - з а п р о с а используется метод
QueryFields объекта типа TWebRequest.
Например:
var1:=Request.QueryFields.Values["Имя_поля"];
var1:=Request.QueryFields.ValueFromIndex[0];
Для доступа к значению ф о р м ы из POST-запроса используется ме
тод ContentFields объекта типа TWebRequest.
Например:
var1:=Request.ContentFields.Values["Имя_поля"];
var1:=Request.ContentFields.ValueFromIndex [ 0 ] ;
Д л я доступа к параметрам самого запроса используется метод
GetFieldByName:
Например:
Request.GetFieldByName( 'URL');
Request.GetFieldByName('METOD'); // Эквивалентно
// выполнению Request.Metod;
Применение Cookies
Cookies — это данные, сохраняемые на П К клиента (web-браузера).
Пользователь имеет возможность запретить сохранять Cookies на своем
П К . Если запись Cookies разрешена, то они записываются при каждом
получении ответа от web -сервера и передаются обратно с каждым следу
ющим HTTP-запросом.
Для задания Cookies следует в обработчике события действия ввести
следующий код:
321
Курс
Введение в программирование
with Response.Cookies.Add
do
Name:='Cook1''; // Им данных
Value:='ValueCook1''; // Значение
end;
Для запроса Cookies следует в обработчике события действия ввести
следующий код:
s1:=Request.CookieFields.ValueFromIndex[0];
// Request.CookieFields.Count
- число полей в Cookies
С о з д а н и е W e b - ф о р м В VisualStudio .NET
Web-формы м о ж н о добавлять в следующие проекты .NET:
A S P . N E T Web Site
ASP.NET. Web Service
Empty Web Site
Personal Web Site Starter K i t
Р а с п о л о ж и т ь п р о е к т м о ж н о к а к в ф а й л о в о й с и с т е м е , т а к и н а webсервере. Е с л и в ы б р а н о р а с п о л о ж е н и е H T T P , то д л я л о к а л ь н о г о с е р в е
р а п о л е L o c a t i o n следует установить р а в н ы м http//localhost/ката•
•
•
•
лог_проекта.
П р и создании проекта типа A S P . N E T Web Site мастер проекта фор¬
мирует следующие ф а й л ы web -приложения:
• Default.aspx — текст H T M L - с т р а н и ц ы :
• D e f a u l t . a s p x . c s — п о д к л ю ч а е м ы е п р о с т р а н с т в а и м е н и метод
Page_Load.
В проект м о ж н о добавлять ранее созданные таблицы стилей.
Таблицы стилей добавляются как н о в ы й элемент. П р и этом в проект
добавляется файл с расширением css (например, StyleSheet. css).
Следующий код иллюстрирует A S P - ф а й л , используемый для отобра
ж е н и я ф о р м ы с 4 элементами управления:
// D e f a u l t . a s p x . c s
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
322
Лекция 28
Серверные приложения
using System.Web. UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public p a r t i a l class _Default
: System.Web.UI.Page
{ p r o t e c t e d v o i d Page_Load(object sender, EventArgs e)
{
}
}
// D e f a u l t . a s p x
<%@ Page Language="C#" AutoEventWireup="true"
C o d e F i l e = " D e f a u l t . a s p x . c s " I n h e r i t s = " _ D e f a u l t " %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 T r a n s i t i o n a l / / E N "
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
< t i t l e > U n t i t l e d Page</title>
<link rel=stylesheet type="text/css"
h r e f = S t y l e S h e e t . c s s />
</head>
<script language="javascript" type="text/javascript">
// <!CDATA[
function Submit1_onclick() {
alert("1234567");
}
// ]]>
</script>
</head>
<body>
<form id="form1" runat="server">
<div Ш ^ ^ ' З а г о л о в о к ^
<input id="Text1" type="text"
c l a s s = " C l 1 " value="12345" />
<input id="Checkbox1" checked="checked"
s t y l e = " w i d t h : 52px; height: 56px"
title="Флажок1"
type="checkbox" />
<input id="Button1" Ш ^ ^ ' К н о п к а 1"
type="button" value="button" />
<input id="Submit1" type="submit" value="submit"
323
Курс
Введение в программирование
onclick="return Submit1_onclick()"
/>
</div>
</form>
</body>
</html>
// S t y l e S h e e t . c s s - файл таблицы стилей
body
{ f o n t - s i z e : 18pt;
c o l o r : blue;
}
.Cl1
{ f o n t - s i z e : 24pt;
c o l o r : red;
}
Таблица стилей содержит набор селекторов с описанием стиля для каж
дого селектора. Селектором может быть имя тега, имя класса (указываемое
после символа «.»), имя идентификатора (указываемое после символа «#»).
Описание стиля для селектора указывается в виде списка, разделен
ного символами «;» и заключенного в фигурные скобки. Описание стиля
состоит из пар «имя_атрибута: значение».
Подключение таблицы стилей выполняется в заголовке H T M L - ф а й
ла строкой < l i n k r e l = s t y l e s h e e t type="text/css" href=StyleSheet.css />.
Строка <%@
Page Language="C#" AutoEventWireup="true"
CodeFile=
"Default.aspx.cs" Inherits="_Default" °%> содержит тег Page, представляющий
HTML-страницу. Атрибут CodeFile указывает файл кода класса, производно
го от любого класса, наследуемого от System.Web.UI. Page. Атрибут Language
определяет язык, используемый при компиляции конструкций вида <°° °°> и
<%= %>. В качестве языка может выступать любой язык программирования,
поддерживаемый . N E T Framework, включая Visual Basic, C# или Jscript. Для
любой страницы может быть указан только один используемый язык.
Страницы A S P . N E T состоят из двух частей:
• визуальных элементов, включающих разметку, серверные элементы
и статический текст;
• программных фрагментов, включающих обработку событий и дру¬
гой в ы п о л н и м ы й код.
Технология A S P . N E T предоставляет две модели управления визуаль¬
н ы м и элементами и кодом:
• модель простого файла (single-file page model), при которой на страни
це описываются визуальные элементы, разметка и выполняемый код;
324
Лекция 28
Серверные приложения
• модель страницы с последующим кодом (code-behind page model),
при которой на странице описываются визуальные элементы и раз
метка, а код р а з м е щ а е т с я в о т д е л ь н о м ф а й л е (таком к а к
Default.aspx.cs).
В следующей таблице приведен пример H T M L - с т р а н и ц ы , разрабо¬
т а н н о й на базе этих двух моделей.
Модель простого файла
Модель страницы
с последующим кодом
<%@ Page Language="C#" %>
< s c r i p t runat="server">
v o i d B u t t o n 1 _ C l i c k ( O b j e c t sender,
EventArgs e)
<%@ Page Language="C#"
CodeFile="MyPage.aspx.cs"
I n h e r its="MyPage"
AutoEventWireup="true" °%>
<html>
<head r u n a t = " s e r v e r " >
< t i t l e > C o d e - B e h i n d Page
Model</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label i d = " L a b e l 1 "
runat="server"
Text="Label" >
</asp:Label>
<br />
<asp:Button i d = " B u t t o n 1 "
runat="server"
onclick="Button1_Click"
Text="Button" >
</asp:Button>
</div>
</form>
</body>
</html>
{
L a b e l 1 . T e x t = "Время: " +
DateTime.Now.ToString();
}
</script>
<html>
<head>
< t i t l e > S i n g l e - F i l e Page
Model</title>
</head>
<body>
<form runat="server">
<div>
<asp:Label i d = " L a b e l 1 "
runat="server"
Text="Label">
</asp:Label>
<br />
<asp:Button i d = " B u t t o n 1 "
runat="server"
onclick="Button1_Click"
Text="Button">
</asp:Button>
</div>
</form>
</body>
</html>
// Файл MyPage.aspx.cs
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
p u b l i c p a r t i a l c l a s s MyPage :
System.Web.UI.Page
{
protected void Button1_Click(object
s e n d e r , EventArgs e ) {
Label1.Text = "Время: " +
DateTime.Now.ToString(); }
}
325
Курс
Введение в программирование
Различие между двумя моделями A S P . N E T страниц существует только
на этапе проектирования. После компиляции страницы, спроектирован
ные на базе различных моделей, представляются одинаковым образом.
П р и использовании модели страницы с последующим кодом в код
класса автоматически добавляется метод Page Load, выполняемый перед
отображением страницы. Так, в этот метод м о ж н о вставить код, в ы п о л н я
ю щ и й и н и ц и а л и з а ц и ю некоторых полей формы. Этот ж е метод м о ж н о
вставить и как скрипт в начало файла при использовании модели просто¬
го файла.
Например:
// Форма:
<form id="form1"
runat="server">
<asp:Label id="Message1"
runat="server"/>
<asp:Button id="Button1" Text="abc"
runat="server" />
</form>
// Код метода:
<%@ Page Language="C#" %> < s c r i p t runat="server">
p r o t e c t e d v o i d Page_Load(object sender, EventArgs e)
{
S t r i n g B u i l d e r sb = new S t r i n g B u i l d e r ( ) ;
i f (Page.IsPostBack)
// Страница отображается как
// обратное сообщение клиенту
sb.Append("Ответ<br>");
sb.Append("HOST:
" + Page.Request.UserHostAddress + ".<br>");
Message1.Text = s b . T o S t r i n g ( ) ;
// Запись в элемент
// управлени типа Label
// с ID равным Message1
}
</script>
326