ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы.



 

Часть 1

 ЪДДДДДДДДДДї
 і Файл ZTC і                (c)  Отделение  4  НФ ИТМ и ВТ
 і 18.07.90 і                     ДДДДДДДДДДДДДДДДДДДДДДДДД
 АДДДДДДДДДДЩ


      Система программирования   Z O R T E C H   C + +

        ( Z O R T E C H   C + +   C O M P I L E R )


 The World's First 'TRUE' C++ Compiler for MS-DOS Machines
 ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
 Первый в мире "истинный" компилятор С++ для машин с MS-DOS


                В  США  поставляется  фирмой

 Zortech Inc, 366 Massachusetts Avenue, Arlington, MA02174
            Tel: 617-646-6703, fax: 617-643-7969

    и  для  всего  остального  мира  фирмой  UK Office:

  Zortech Limited, 106-108 Powis Street, LONDON, SE18 6LU
             Tel: 01-316-7777,  fax: 01-316-4138

 ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
 і      Перевод Руководства "Zortech C++ Compiler":       і
 і                                                        і
 і Part One: The User Guide - Руководство пользователя    і
 і Part Two: The Reference Guide - Справочное руководство і
 і Part Three: Function Library - Библиотека функций      і
 і Appendixes   -  Приложения                             і
 і                                                        і
 і        Перевод выполнен в Новосибирском филиале        і
 і   Института точной механики и вычислительной техники   і
 і                   им. С.А. Лебедева                    і
 і                                                        і
 і               630090, г. Новосибирск-90,               і
 і            проспект академика Лаврентьева, 6           і
 і                  НФ ИТМ и ВТ АН СССР                   і
 і                                                        і
 і     Авторы перевода: Гутман А.А., Игнатенко П.С.,      і
 і                      Касторнов Е.А., Степанов В.П      і
 і                                                        і
 і                 Тел: (8-383-2)324-159, 324-144         і
 і                               ДДДДДДД  ДДДДДДД         і
 і                                                        і
 і                     Новосибирск 1990                   і
 АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

                         Аннотация

   Zortech C++ является первым  кодопорождающим компилятором
для машин с MS-DOS. Это значит,  что  Вам  не  нужно тратить
деньги на С-компилятор. В самом деле,  сейчас  Вы  держите в
руках ряд компонент:  компилятор  С++,  С-компилятор, линкер
(редактор  связей), библиотекарь, полное интегрированное ок-
ружение редактора,  контекстно  зависимые  подсказки(help) и
библиотеку графики,  самую  скоростную  из  всех,  какие  Вы
когда-нибудь встречали!
   Пользуясь  Zortech  C++,  Вы имеете возможность совместно
использовать и согласовывать  коды на C++, C,  ассемблере, а
также  связывать их воедино одной командой!
   Zortech C++ включает  полные  библиотеки C++ и C, он сов-
местим с ANSI-стандартом на язык C.  Zortech C++  уникален в
своей  поддержке мыши,  быстрого  вывода на экран,  повторно
входимой  библиотеки вычислений с плавающей точкой и библио-
теки генерации звука.

   Теперь Вы можете перенести Ваши коды из  Microsoft C  или
Turbo C в систему Zortech C++ - имеет место полная совмести-
мость библиотечных функций!

   В Zortech C++ обеспечена также и совместимость с отладчи-
ком Codeview фирмы Microsoft!

   Войдите в мир объектно-ориентированных  систем программи-
рования(ООСП), используя  Zortech C++!

   Конечно, С велик, но С++ лучше!


   Сравнительные показатели испытаний (benchmarks)
  ЪДДДДДДДДДДДДДДДДВДДДДДДДДВДДДДДДДДДДВДДДДДДВДДДДДДДДДДї
  іВид испытания   іZortechCіZortechC++іTurboCіQuickC 1.0і
  ГДДДДДДДДДДДДДДДДЕДДДДДДДДЕДДДДДДДДДДЕДДДДДДЕДДДДДДДДДДґ
  іSieve ("решето")і  20.49 і  20.54   і 23.62і   22.72  і
  іRsieve          і  20.49 і  20.54   і 23.62і   22.03  і
  іInteger         і   1.32 і   1.38   і  6.31і    6.49  і
  іFloat           і   0.17 і   0.22   і 52.29і   51.03  і
  і'Float          і  32.73 і  37.74   і 52.39і   51.63  і
  іPointer         і  17.91 і  17.96   і 17.13і   16.87  і
  іRpointer        і  17.79 і  17.91   і 17.14і   16.64  і
  іLoop            і  3.90  і  3.90    і 3.90 і    3.90  і
  іOptimize        і  0.49  і  0.60    і 8.46 і    8.79  і
  АДДДДДДДДДДДДДДДДБДДДДДДДДБДДДДДДДДДДБДДДДДДБДДДДДДДДДДЩ
   Испытания проводились  на ПЭВМ  с микропроцессором 80286,
совместимой с IBM PC, с тактовой частотой 6 Мгц и без сопро-
цессора 8087

              Лицензионное обращение фирмы Zortech
              ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
   1. Пожалуйста,  не раздавайте копии этого продукта  своим
друзьям, склоняйте  их  к приобретению  законной копии.  Это
единственный источник  вознаграждения  программистов, техни-
ческих писателей  и служащих  фирмы Zortech за их невероятно
большой вклад в создание этого продукта.
   2. Пожалуйста,  не  загружайте  эту  систему более чем на
одной  ПЭВМ  Вашего  рабочего места - это незаконно и, кроме
того,  лишает программистов и издателей их законных заработ-
ков.
   3. С этой  системой  обращайтесь  как  с книгой:  подобно
тому, как двоим нелегко читать одну  и  ту  же  книгу в одно
время, а каждому из них нужно  приобрести собственную копию,
так и для пользования данным  продуктом,  пожалуйста, купите
узаконенную копию.
   4. Zortech Ltd, ее филиалы, а также поставщики,  дилеры и
служащие не могут нести финансовые потери, вызванные аварией
или слабостью этого продукта.



                         ПРЕДИСЛОВИЕ

   Этот продукт является первым кодопорождающим компилятором
C++ для машин типа IBM PC/XT/AT. "Кодопорождающий" означает,
что Вам не требуется  тратить  массу денег на еще какой-либо
C-компилятор.  Действительно, Вы только что приобрели и ком-
пилятор C++,  и C-компилятор,  и линкер,  и библиотекарь,  и
мощную утилиту make. Теперь Вам можно совместно использовать
и согласовывать коды C++, C и ассемблера. Мы включили "взры-
вной" редактор (ZED), который запускает компилятор, останав-
ливает  компиляцию  при обнаружении  ошибки и соответственно
устанавливает курсор для облегчения исправления.

   Zortech C++ включает  полные библиотеки C++ и C,  в т. ч.
поддержку  мыши,  быстрого  вывода  на  экран,  обращений  к
BIOS/DOS и обработки  прерываний.  Для  динамической отладки
можно воспользваться  отладчиком  Codeview  фирмы Microsoft.
В целом,  это  мощная  и недорогая  объектно-ориентированная
система разработки программ для ПЭВМ.

   C++ разработан в Bell Labs и представляет собой объектно-
-ориентированное расширение языка C.  Поэтому Вы легко може-
те компилировать уже существующий C-код  и использовать рас-
ширения  по  мере  их  освоения.  В дополнение к этому,  C++
обеспечивает  лучший по сравнению с  имеющимся  в C контроль
ошибок,  что  помогает быстрее находить их.  Поскольку C++ -
объектно-ориентированный язык, то Вы можете создавать собст-
венные типы данных.  Это может сделать решение Ваших проблем
более четким.  Например, разрабатывая  систему  картирования
погоды,  Вы создаете  тип данных  под названием  StormFront,
описываете  несколько  таких  StormFront,   перемещаете  их,
комбинируете их, делаете дождливыми и т. д.  Это высокоуров-
невое представление, на котором Вы можете решать более комп-
лексные задачи.

   C++  поможет Вам легко переиспользовать  старый код (даже
если это только объектные файлы без исходных текстов).  Если
Вы астроном, а кто-то  описал  некий  тип данных,  названный
MassiveBody, который представляет собой не совсем то, что Вы
хотите,  то  Вы  можете сказать:  Asteroid - это MassiveBody
с соответствующими изменениями и дополнениями.

   Вам  даже не надо понимать,  как работает  MassiveBody, а
всего лишь надо знать, что он делает. Поскольку Вам потребу-
ется  написать  и отладить только изменения и дополнения, то
и результаты Вы получите скорее.

   Пользуясь C++, Вы обнаружите, что структура языка практи-
чески организует Ваш код (структурирует программу). Начинай-
те  с  процесса  создания  каких-то  частей  Вашего  проекта
(StormFront, Asteroid). Однажды отлаженные, они моменталь-
но  интегрируются  с  остальными  (и  компилятор  генерирует
ошибки,  если  Вы  пытаетесь  делать с типом что-нибудь, для
чего он не предназначен).

   Цель C++ - помочь Вам программировать быстрее, причем без
потери эффективности,  т. е. Вы увидите,  что Ваши программы
на C++,  как правило, такие  же  короткие  и  быстрые, как и
C-программы.


                    Группа  разработчиков

   Walter Bright - вдохновитель и руководитель работы
   Bruce Eckel   - C++ тексты и beta-тестирование
   Bjorn Freeman - Benson - Zortech LINKER (редактор связей)
   Steve Teal    - Zortech HOTLINE
   Joe Huffman   - скоростная графическая библиотека
   Nikki Locke   - окружение редактора ZED
   Kevin Powis - система контекстно зависимых подсказок HELP
   Dave Morton   - MANUAL (Руководство)
   Mark Welsh    - Подготовка руководства к печати
   Dave Mansell  - (техническое обеспечение)
   Tanj Bennett  - LIBRARIAN (библиотекарь)

   Bjarne Stroustrup  выражается  особая  признательность за
                                                книгу по C++


                    С о д е р ж а н и е


Часть 1:  Р У К О В О Д С Т В О   П О Л Ь З О В А Т Е Л Я


БЫСТРЫЙ  СТАРТ  ........................................  18

   Кратко об установке
   Кратко о редактировании  ............................  19


ВВЕДЕНИЕ  В  C++  ......................................  21

   Объектно-ориентированное программирование  ..........  22
      Эффективность  ...................................  23
   Краткие предварительные сведения
      Объявления и описания
      Прототипирование функций  ........................  24
      Использование файлов заголовков для объявления классов
      Краткое введение в потоки  .......................  25
   Классы - определение Ваших собственных типов  .......  26
      Полный пример  ...................................  27
      Совместное использование функций
        (function overloading)  ........................  30
      Совместное использование операций
        (operator overloading)  ........................  32
   Создание нового типа из старого типа  ...............  34
   По окончании базового курса  ........................  38
   Дальнейшая помощь в работе


БОЛЕЕ  СЛОЖНЫЙ  C++  ...................................  39

   Вызов функций-членов
   Константы
   Комментарии
   Многократные включения файлов заголовков  ...........  40
   Области действия
   Открытые (inline) функции  ..........................  41
   Функции доступа
   Динамическое распределение памяти  ..................  42
   Конструкторы и деструкторы  .........................  43
   Ссылки  .............................................  44
   Совместное использование операций
     (operator overloading)  ...........................  47
   Операция присваивания (operator=())
   Указатель на void  ..................................  49
   Виртуальные функции
   Друзья (friends)  ...................................  51
   Общие, приватные, защищенные (Public, Private, Protected)
   Статические переменные  .............................  52
   Операция разрешения области действия



Часть 2:  С П Р А В О Ч Н О Е   Р У К О В О Д С Т В О


ПОДРОБНОЕ  РУКОВОДСТВО  ПО  УСТАНОВКЕ  СИСТЕМЫ  ........  53

   Системные требования
   Установка системы на жесткий диск
      Переменные окружения  ............................  54
      Изменение маршрутов к каталогам (directory paths)
        и переменных окружения  ........................  55
      Переменная окружения CFLAGS  .....................  57
   Установка системы на гибкий диск


КОНТЕКСТНО  ЗАВИСИМЫЕ  ПОДСКАЗКИ (Context sensiTive HELP) 57

   Введение
   Конфигурирование системы  ...........................  58
   Установка системы  ..................................  59
   Загрузка резидентного подсказчика
   Удаление резидентного подсказчика
   Вызов подсказки  ....................................  60
      Сводный список клавиш


ОКРУЖЕНИЕ  РЕДАКТИРОВАНИЯ - ZED  .......................  61

   Вход в редактор  ....................................  62
   Привязки клавиш  ....................................  63
   Функциональные клавиши  .............................  64
   Клавиши управления курсором  ........................  65
   Клавиши, совместимые с системой Wordstar  ...........  66
   Прочие управляющие клавиши  .........................  67
   Дополнительные клавиши (клавиши с Alt)
   Подсказки во время работы  ..........................  70
   О меню
   Главное меню  .......................................  71
   Меню "файлы" (Files)  ...............................  72
      Ввод имен файлов  ................................  74
      Меню "размер" (Size)  ............................  76
   Меню "перемещение курсора" (Moves)
   Меню "редакция" (Edit)  .............................  78
      Меню "размер" (Size)  ............................  81
   Меню "блоки" (Blocks)  ..............................  82
   Меню "удаление" (Delete)  ...........................  84
   Меню "поиск" (Search)  ..............................  85
      Ввод строк  ......................................  86
   Меню "прочее" (Other) ...............................  87
      Ввод строк  ......................................  88
   Компиляция
      Компиляция проектов с многими исходными файлами     91
      Отладка и исполнение программ ДОС
   Проблемы с MS-DOS  ..................................  92
   Меню "запись" (Record) и "извлечение" (Playback) ....  93
   Меню "текст" (Text)  ................................  94
      Форматирование и автоматическая втяжка
        (formatting and autoindent)  ...................  95
   Предыдущая версия файла  ............................  96
   Структура меню
   Конфигурирование  ...................................  97
      Установка быстрых командных клавиш (Hotkeys)
      Установка маршрутов (Files)  ..................... 104
      Вид экрана (Screen)
      Цвета экрана (Colors and More colors)  ........... 107
      Разметка экрана (Lines)  ......................... 108
      Позиции окон  .................................... 109
      Обрамление окон (Boxes)
      Распечатка конфигурирации (Print)  ............... 110
      Сохранение конфигурации (saVe) и выход (eXit)
         Файл подсказок


КОМПИЛЯТОР  ZORTECH  ................................... 111

   Обзор процесса компиляции

      ZTC1.EXE, ZTC1B.EXE и ZTCPP1.EXE  ................ 112
         Командная строка
         Входной файл  ................................. 113
         Ключи
         Переменные окружения  ......................... 117
      ZTG.EXE
         Командная строка
         Прочие ключи  ................................. 118
      ZTC2.EXE и ZTC2B.EXE  ............................ 119
         Входной файл
         Ключи
      Команда ZTC  ..................................... 120
         Переменные окружения  ......................... 122


СПРАВОЧНИК  ПО  C++  ................................... 123

   Комментарии
   Идентификаторы
      Ключевые слова
      Конфликты с библиотечными именами
   Литерные константы  ................................. 124
   Типы  ............................................... 125
   Kонстанты и неявно изменяющиеся переменные
     (const и volatile)
   Bнешние и глобальные переменные  .................... 126
   Выравнивание данных  ................................ 127
   Параметры функций
   Указатели  .......................................... 128
   Инициализация
   Операции с плавающей точкой
   Препроцессор  ....................................... 129
   Макросы
   Предопределенные макросы  ........................... 130
   Включаемые файлы  ................................... 131
   Прочие директивы препроцессора
   Ограничения  ........................................ 132
   Прототипирование функций
      Индуцированное прототипом приведение (cast)  ..... 134
      Прототипирование - char и float
   Автопрототипирование
   Совместимость с C  .................................. 135
   Определенные пользователем приведения типов  ........ 136
   Совместимость с C++ фирмы AT&T
   Замечания, ошибки, предупреждения при программиро-
     вании на C++  ..................................... 137
   Совместное использование модулей на C и C++  ........ 138
      Разное  .......................................... 139



ПРОГРАММЫ  РЕДАКТИРОВАНИЯ  СВЯЗЕЙ  ..................... 141

   BLINK.EXE
      Работа с ZTC  .................................... 142
      Использование
      Ключи
      Переменные окружения  ........................... 143
      Различия между BLINK и MS-LINK  ................. 144

   BUNCH.EXE  ......................................... 145
      Назначение
      Работа с ZTC
      Использование
      .COM-файлы  ..................................... 146
      Переменные окружения
      Пример
      Ошибки
   EXE2BIN.COM
   Целочисленные программы  ............................ 147
   Создание .COM-программ


ИСПОЛНЕНИЕ  ПРОГРАММ  .................................. 148

   Расширение командной строки аргументов  ............. 149
   Управление размером стека  .......................... 150


ГЛОБАЛЬНЫЙ  ОПТИМИЗАТОР  ............................... 151

   Введение
      Что такое глобальная оптимизация
      Зачем это нужно
      Когда мне использовать его
      Какого улучшения скорости можно мне ожидать  ..... 152
      Делает ли Глобальный оптимизатор ненужным програм-
                                 мирование на ассемблере
      Чего не умеет Глобальный оптимизатор

   Использование  ...................................... 153
      Запуск оптимизатора посредством ZTC
      Автономный запуск
      Другие режимы  ................................... 154

   Дальнейшая информация  .............................. 155
      Распространение констант (+cnp)
      Распространение копий (+cp)
      Удаление излишних присваиваний (+da)  ............ 156
      Удаление неисполняемого кода (+dc)
      Удаление излишних переменных,
       вычисление границ существования,
       распределение регистров при помощи раскраски (+dv)
      Глобальные общие подвыражения (+gcse)  ........... 157
      Вынесение инвариантов из цикла (+li)
      Индуктивные переменные цикла (+liv)
      Итерация до отсутствия дальнейших оптимизаций(+loop)
      Выполнять наше распределение регистров (+reg)
      Соотношение между памятью и скоростью
                                       (+space и +time)
      Очень нагруженные выражения (+vbe)  .............. 159

   Советы и замечания
      Использование ключевых слов const и volatile
      Если возникли проблемы  .......................... 160


СЛОЖНЫЕ  ЧЕРТЫ  СИСТЕМЫ  ............................... 161

   Модели памяти
      Сегментная архитектура 8088/8086
      Пять различных моделей [памяти]  ................. 162
      Выбор модели памяти
   Указатели  .......................................... 163
      Ближние указатели
      Дальние указатели
      Макросы для работы с дальними указателями  ....... 164
      Нормализация дальних указателей
      Арифметика над дальними указателями  ............. 165
   Использование ключевых слов near и far  ............. 166
      Использование ближних указателей  ................ 167
      Использование дальних указателей
      Преобразования между ближними и дальними указателями
   Подавление выравнивания в структурах  ............... 168
   Отладка C++ программ  ............................... 169
     Использование отладчиков
     Другая поддержка
     Отладка с CodeView  ............................... 170


ИНСТРУМЕНТАРИЙ  ........................................ 171

   MAKE
      Что такое MAKE
      Начало работы с MAKE
      Командный файл для MAKE (MAKEFILE)  .............. 172
      Пример MAKEFILE
      Файлы зависимости  ............................... 173
      Второй пример
      MAKEFILE при нескольких исходных файлах
      Запуск MAKE  ..................................... 174
      Использование аргументов MAKE  ................... 175
      Определенные пользователем макросы  .............. 176
      Предопределенные макросы
      Режимы исполнения правил  ........................ 177
      Внутренние команды MS DOS
      Специальные цели  ................................ 178
      Перенаправление вывода
      Неявные правила
      Создание командных файлов для редактора связей ... 179
      Список отличий от MAKE системы Юникс  ............ 180
   TOUCH
   OBJTOASM  ........................................... 181
      Использование


ИНТЕРФЕЙС  С  АССЕМБЛЕРОМ  ............................. 182

   Программные разделы
      T-модель памяти (.COM программы)
      S-модель памяти  ................................. 183
      M-модель памяти  ................................. 184
      C-модель памяти  ................................. 185
      L-модель памяти  ................................. 186
   Общее размещение  ................................... 188
   Сборка подпрограмм
   Область стека  ...................................... 189
   Возвращаемые функциями значения
   Использование регистров  ............................ 190
   Выравнивание данных
   Макросы из MACROS.ASM
   Простой пример для S-модели  ........................ 191
   Следующий пример  ................................... 193
   Запуск MASM  ........................................ 195





Часть 3:  Б И Б Л И О Т Е К А   Ф У Н К Ц И Й



БИБЛИОТЕКА  ФУНКЦИЙ  ................................... 196

   Обмен с файлами  .................................... 197
      Виды файлов
      Высокий и низкий уровни обмена с файлами
   Распределение памяти  ............................... 198
      Куча (heap)
      Стек  ............................................ 199
   Глобальные переменные  .............................. 200
      _8087
      _okbigbuf  ....................................... 204
      _osmajor  ........................................ 205
      _osminor
      _psp
      errno


СООБЩЕНИЯ  ОБ  ОШИБКАХ  ................................ 206

   Ошибки ДОС
   Ошибки математических функций  ...................... 207



ФАЙЛЫ  ЗАГОЛОВКИ  ...................................... 207

   assert.h
   conio.h  ............................................ 208
   ctype.h
   direct.h
   disp.h
   dos.h
   fg.h  ............................................... 209
   errno.h  ............................................ 211
   int.h
   io.h
   limits.h
   math.h
   msmouse.h  .......................................... 212
   process.h
   setjmp.h
   signal.h
   sound.h
   stdarg.h
   stddef.h  ........................................... 213
   stdio.h
   stdlib.h
   string.h  ........................................... 214
   sys\stat.h
   time.h


БИБЛИОТЕЧНЫЕ  ФУНКЦИИ  ................................. 215

   abort  -  СБРОСИТЬ ВЫПОЛНЕНИЕ ПРОГРАММЫ ............. 216
   abs  -  АБСОЛЮТНОЕ ЗНАЧЕНИЕ ЦЕЛОГО  ................. 217
   acos  -  АРККОСИНУС  ................................ 217
   asctime  -  ДАТЬ ВРЕМЯ  ............................. 218
   asin  -  АРКСИНУС  .................................. 219
   assert  -   ПРОВЕРИТЬ УТВЕРЖДЕНИЕ  .................. 220
   atan, atan2  -  АРКТАНГЕНС  ......................... 221
   atof, atoi, atol  -  ПРЕОБРАЗОВАТЬ В ПЛАВАЮЩЕЕ,
                        ПРЕОБРАЗОВАТЬ В ЦЕЛОЕ,
                        ПРЕОБРАЗОВАТЬ В ДЛИННОЕ ........ 222
   bdos, bdosx  -  ВЫЗВАТЬ ФУНКЦИЮ DOS  ................ 222
   bioskey, _bios_keybrd  -  РАБОТА С КЛАВИАТУРОЙ  ..... 223
   bsearch  -  ДВОИЧНЫЙ ПОИСК В МАССИВЕ ................ 225
   calloc  -  ДАТЬ ПАМЯТЬ  ............................. 226
   ceil  -  ЦЕЛАЯ ВЕРХНЯЯ ГРАНЬ  ....................... 227
   chdir  -  СМЕНИТЬ ТЕКУЩИЙ КАТАЛОГ  .................. 227
   _chkstack  - ПРОВЕРИТЬ СТЕК  ........................ 228
   clearerr  -  СБРОСИТЬ ФЛАГ ОШИБКИ ................... 229
   clock  -  ОПРЕДЕЛИТЬ ПРОЦЕССОРНОЕ ВРЕМЯ ............. 230
   close  -  ЗАКРЫТЬ ФАЙЛ .............................. 230
   cos, cosh  -  КОСИНУС, КОСИНУС ГИПЕРБОЛИЧЕСКИЙ  ..... 231
   creat  -  СОЗДАТЬ ФАЙЛ .............................. 232
   ctime  -  ДАТЬ КАЛЕНДАРНОЕ ВРЕМЯ  ................... 233
   difftime  -  ОПРЕДЕЛИТЬ ОТРЕЗОК ВРЕМЕНИ  ............ 234
   Display Package  -  Пакет отображения  .............. 235
   div  -  ДЕЛИТЬ  ..................................... 239
   DOS Package  -  Пакет функций DOS  .................. 240
   ecvt  -  ПРЕОБРАЗОВАТЬ ЧИСЛО В СТРОКУ  .............. 242
   execl - execvp  -  ЗАПУСТИТЬ ПРОЦЕСС ................ 243
   exit, _exit  -  ЗАВЕРШИТЬ ВЫПОЛНЕНИЕ ПРОГРАММЫ ...... 245
   exp  -  ЭКСПОНЕНТА  ................................. 246
   fabs  -  АБСОЛЮТНОЕ ЗНАЧЕНИЕ ВЕЩЕСТВЕННОГО  ......... 247
   farcalloc - farrealloc  -  РАБОТА С ДАЛЬНЕЙ КУЧЕЙ ... 248
   _farptr_norm, _farptr_fromlong, _farptr_tolong  -
                     НОРМАЛИЗОВАТЬ ДАЛЬНИЙ УКАЗАТЕЛЬ,
		     ДАЛЬНИЙ УКАЗАТЕЛЬ ИЗ ДЛИННОГО,
                     ДАЛЬНИЙ УКАЗАТЕЛЬ В ДЛИННОЕ  ...... 249
   fclose  -  ЗАКРЫТЬ ФАЙЛ  ............................ 250
   fcvt  -  ПРЕОБРАЗОВАТЬ DOUBLE В СТРОКУ С ФИКСИРО-
            ВАННОЙ ТОЧКОЙ  ............................. 251
   feof  -  ПРОВЕРКА ПРИЗНАКА КОНЦА ФАЙЛА  ............. 252
   ferror  - ПРОВЕРКА ПРИЗНАКА ОШИБКИ В ФАЙЛЕ .......... 253
   fflush  -  ВЫТОЛКНУТЬ БУФЕР ФАЙЛА  .................. 254
   fgetc  -  ВЗЯТЬ БАЙТ ИЗ ФАЙЛА  ...................... 254
   fgets  -  ВЗЯТЬ СТРОКУ ИЗ ФАЙЛА  .................... 255
   fileno  - ДАТЬ ДЕСКРИПТОР ФАЙЛА  .................... 256
   filesize  - ДАТЬ РАЗМЕР ФАЙЛА  ...................... 257
   findfirst, findnext - ПОИСК ФАЙЛОВ ПО ШАБЛОНУ ....... 257
   floor  -  ЦЕЛАЯ ЧАСТЬ  .............................. 259
   flushall  -  ВЫТОЛКНУТЬ БУФЕРА ВСЕХ ОТКРЫТЫХ ФАЙЛОВ   259
   fmod  -  ОСТАТОК ОТ ДЕЛЕНИЯ ДВУХ ЧИСЕЛ .............. 260
   fopen  -  ОТКРЫТЬ ФАЙЛ  ............................. 261
   FP_OFF, FP_SEG  -  СЕГМЕНТ, СМЕЩЕНИЕ  ............... 262
   fprintf  -  ФОРМАТНЫЙ ВЫВОД В ФАЙЛ  ................. 263
   fputc  -  ЗАПИСЬ БАЙТА В ФАЙЛ  ...................... 263
   fputs  -  ЗАПИСЬ СТРОКИ В ФАЙЛ  ..................... 264
   fread  -  ЧИТАТЬ ИЗ ФАЙЛА  .......................... 265
   free  -  ОСВОБОДИТЬ ПАМЯТЬ  ......................... 266
   freopen  -  ОТКРЫТЬ ФАЙЛ ПОВТОРНО  .................. 266
   frexp  -  ЭКСПОНЕНЦИАЛЬНОЕ ПРЕДСТАВЛЕНИЕ  ........... 267
   fscanf  -  ФОРМАТНЫЙ ВВОД ИЗ ФАЙЛА  ................. 268
   fseek  -  ПОЗИЦИОНИРОВАТЬ ФАЙЛ  ..................... 269
   fstat  -  ВЗЯТЬ СТАТУС ФАЙЛА  ....................... 270
   ftell  -  ДАТЬ ПОЗИЦИЮ В ФАЙЛЕ  ..................... 271
   fwrite  -  ПИСАТЬ В ФАЙЛ  ........................... 272
   getc, getchar, getche, getch  -  ВЗЯТЬ БАЙТ ИЗ ФАЙЛА  273
   getcwd  -  ДАТЬ ТЕКУЩИЙ КАТАЛОГ  .................... 274
   getDS  -  ВЗЯТЬ ЗНАЧЕНИЕ РЕГИСТРА DS ................ 275
   getenv  -  ДАТЬ ОКРУЖЕНИЕ  .......................... 275
   gets  -  ВВОД СТРОКИ  ............................... 276
   hypot  -  ГИПОТЕНУЗА  ............................... 277
   index  -  НАЙТИ ЛИТЕРУ В СТРОКЕ  .................... 277
   inp, inpw  -  ВВОД ИЗ ПОРТА  ........................ 278
   Interrupt Package  -  Пакет работы с прерываниями ... 279
   int86, int86x  -  ПРОГРАММНОЕ ПРЕРЫВАНИЕ  ........... 282
   intdos, intdosx  -  СИСТЕМНЫЙ ВЫЗОВ ФУНКЦИИ DOS  .... 283
   isatty  -  ОПРЕДЕЛИТЬ ТИП ПОТОКА  ................... 284
   is package  -  Пакет классификации литер  ........... 285
   itoa  -  ПРЕДСТАВЛЕНИЕ ЦЕЛОГО  ...................... 287
   kbhit  -  ПРОВЕРКА ВВОДА С КЛАВИАТУРЫ  .............. 288
   labs  -  АБСОЛЮТНОЕ ЗНАЧЕНИЕ ДЛИННОГО  .............. 288
   ldexp  -  ЭКСПОНЕНТА  ............................... 289
   ldiv  -  ДЕЛЕНИЕ ЧИСЕЛ ТИПА long .................... 290
   localtime  -  ДАТЬ МЕСТНОЕ ВРЕМЯ  ................... 291
   log, log10  -  ЛОГАРИФМ  ............................ 292
   longjmp  -  ДЛИННЫЙ ПЕРЕХОД  ........................ 292
   lseek  -  ИЗМЕНИТЬ ПОЗИЦИЮ В ФАЙЛЕ  ................. 294
   malloc  -  ОТВЕСТИ ПАМЯТЬ  .......................... 295
   matherr  -  ОБРАБОТКА ОШИБКИ МАТЕМАТИЧЕСКОЙ ФУНКЦИИ   296
   memchr - memset  -  РАБОТА С БАЙТАМИ В МАССИВАХ ..... 296
   mkdir  -  СОЗДАТЬ КАТАЛОГ  .......................... 298
   MK_FP  -  СОЗДАТЬ ДАЛЬНИЙ УКАЗАТЕЛЬ  ................ 299
   mktime  -  ПРЕОБРАЗОВАТЬ ВРЕМЯ  ..................... 299
   modf  -  ДРОБНАЯ И ЦЕЛАЯ ЧАСТЬ ЧИСЛА ................ 300
   Mouse Package  -  Пакет работы с мышью  ............. 301
   open  -  ОТКРЫТЬ ФАЙЛ ............................... 302
   outp, outpw  -  ВЫВОД В ПОРТ  ....................... 304
   peek  -  ПЕРЕСЛАТЬ БУФЕР ИЗДАЛЕКА  .................. 305
   perror  -  ВЫДАТЬ СООБЩЕНИЕ ОБ ОШИБКЕ  .............. 306
   poke  -  ПЕРЕСЛАТЬ БУФЕР ДАЛЕКО  .................... 307
   poly  -  ПОЛИНОМ  ................................... 308
   pow  -  СТЕПЕНЬ  .................................... 309
   printf, fprintf, sprintf  -  ФОРМАТНЫЙ ВЫВОД ........ 309
   putc, putchar  -  ВЫВОД ЛИТЕРЫ В ФАЙЛ ............... 313
   puts  -  ВЫВОД СТРОКИ В ФАЙЛ ........................ 314
   qsort  -  БЫСТРАЯ СОРТИРОВКА ТАБЛИЦЫ ................ 315
   raise  -  ВОЗБУДИТЬ СИГНАЛ  ......................... 316
   rand  -  СЛУЧАЙНАЯ ВЕЛИЧИНА  ........................ 317
   read  -  ЧИТАТЬ БЛОК ИЗ ФАЙЛА ....................... 317
   realloc  -  ПЕРЕРАЗМЕСТИТЬ БЛОК ПАМЯТИ .............. 318
   rename  -  ПЕРЕИМЕНОВАТЬ ФАЙЛ ....................... 319
   rewind  -  УСТАНОВИТЬ В НАЧАЛО УКАЗАТЕЛЬ ФАЙЛА  ..... 320
   rmdir  -  УДАЛИТЬ КАТАЛОГ  .......................... 321
   sbrk  -  УВЕЛИЧИТЬ СЕГМЕНТ ДАННЫХ  .................. 322
   scanf  -  ФОРМАТНЫЙ ВВОД  ........................... 323
   segread  -  ЧИТАТЬ СЕГМЕНТНЫЕ РЕГИСТРЫ  ............. 326
   setbuf  -  УСТАНОВИТЬ БУФЕР В/В  .................... 327
   setjmp  -  УСТАНОВИТЬ ТОЧКУ ДЛИННОГО ПЕРЕХОДА  ...... 328
   setvbuf  -  УСТАНОВИТЬ БУФЕР В/В  ................... 328
   signal  -  УСТАНОВИТЬ РЕАКЦИЮ НА СИГНАЛ   ........... 330
   sin, sinh  -  СИНУС, СИНУС ГИПЕРБОЛИЧЕСКИЙ  ......... 332
   Sound Package  -  Пакет работы со звуком  ........... 332
   spawn  -  СОЗДАТЬ ПРОЦЕСС  .......................... 333
   sprintf  -  ФОРМАТНЫЙ ВЫВОД В БУФЕР  ................ 334
   sqrt  -  КВАДРАТНЫЙ КОРЕНЬ  ......................... 335
   srand  -  ИНИЦИАЛИЗАЦИЯ СЛУЧАЙНОЙ ВЕЛИЧИНЫ  ......... 335
   sscanf  -  ФОРМАТНЫЙ ВВОД В БУФЕР  .................. 336
   stat  -  ЧИТАТЬ СТАТУС ФАЙЛА  ....................... 337
   strcat - strdur  -  Работа со строками  ............. 338
   strerror  -  ПОЛУЧИТЬ ИНФОРМАЦИЮ ОБ ОШИБКЕ .......... 339
   strlen  - ДАТЬ ДЛИНУ СТРОКИ  ........................ 340
   strlwr  -  ПРИВЕСТИ К НИЖНЕМУ РЕГИСТРУ  ............. 341
   strncat - strpbrk  -  Работа со строками  ........... 341
   strrchr - strset  -  Работа со строками  ............ 343
   strspn  -  ДАТЬ ДЛИНУ СОВПАДАЮЩЕЙ ПОДСТРОКИ  ........ 344
   strstr  -  НАЙТИ ПОДСТРОКУ  ......................... 344
   strtod - strtoul  -  ПРЕОБРАЗОВАТЬ ИЗ А/Ц ВИДА  ..... 345
   strupr  -  ПРИВЕСТИ К ВЕРХНЕМУ РЕГИСТРУ  ............ 347
   swab  -  ПОПАРНО ПОМЕНЯТЬ БАЙТЫ  .................... 348
   system  -  ОБРАЩЕНИЕ К DOS  ......................... 348
   tan, tanh  -  ТАНГЕНС, ТАНГЕНС ГИПЕРБОЛИЧЕСКИЙ  ..... 349
   time  -  ДАТЬ ВРЕМЯ  ................................ 350
   toascii, tolower, toupper  -  В ASCII,  В НИЖНИЙ,
                                 В ВЕРХНИЙ  ............ 351
   ungetc  -  ВОЗВРАТИТЬ ЛИТЕРУ ........................ 352
   unlink  -  УДАЛИТЬ ФАЙЛ  ............................ 353
   utime  -  ИЗМЕНИТЬ ВРЕМЯ МОДИФИКАЦИИ ФАЙЛА  ......... 353
   va_arg - va_start  -  РАБОТА С ПЕРЕМЕННЫМ ЧИСЛОМ
                         ПАРАМЕТРОВ  ................... 354
   vfprintf, vprintf, vsprintf  -  ФОРМАТНЫЙ ВЫВОД ..... 355
   write  -  ПИСАТЬ В ФАЙЛ ............................. 356



ВВЕДЕНИЕ  В  БЫСТРУЮ  ГРАФИКУ  ......................... 358


   Определение базовой координатной системы
   Типы переменных
   Константы FG  ....................................... 359
   Адаптеры графического дисплея
   Доступ к координатам рамок и линий  ................. 360
   Маски  .............................................. 361
   Запись режимов
   Типы линий
   Доступные цвета  .................................... 362



ОБЩИЕ  ПЕРЕМЕННЫЕ  ..................................... 363

   fg_displaybox  (КООРДИНАТЫ РАМКИ ДИСПЛЕЯ)
   fg_charbox  (КООРДИНАТЫ РАМКИ ЛИТЕРЫ)
   fg_ncolormap  (РАЗМЕР ПАЛИТРЫ)
   fg_nsimulcolor  (ЧИСЛО ЦВЕТОВ)  ..................... 364
   fg_pixelx, fg_pixely  (РАЗМЕРЫ ПИКСЕЛЯ)
   fg_numpages  (ЧИСЛО СТРАНИЦ)
   fg_display  (ТИП АДАПТЕРА)
   fg_activepage  (НОМЕР АКТИВНОЙ СТРАНИЦЫ)  ........... 365
   fg_displaypage  (НОМЕР ОТОБРАЖАЕМОЙ СТРАНИЦЫ)


ФУНКЦИИ, ПОСТАВЛЯЕМЫЕ ПОЛЬЗОВАТЕЛЕМ ФАКУЛЬТАТИВНО ...... 365

   _assert  -  УТВЕРЖДЕНИЕ
   fg_lineclip  -  КЛИППИРОВАНИЕ ЛИНИИ  ................ 366


ОБЩИЕ  ФУНКЦИИ  БЫСТРОЙ  ГРАФИКИ  ...................... 366

   fg_adjustxy  -  СКОРРЕКТИРОВАТЬ ТЕКУЩИЕ КООРДИНАТЫ    366
   fg_blit  -  ПЕРЕМЕСТИТЬ РАМКУ  ...................... 367
   fg_box_cpy  -  СКОПИРОВАТЬ РАМКУ  ................... 368
   fg_drawarc  -  НАРИСОВАТЬ ДУГУ  ..................... 368
   fg_drawbox  -  НАРИСОВАТЬ ПРЯМОУГОЛЬНИК  ............ 369
   fg_drawdot  -  НАРИСОВАТЬ ТОЧКУ  .................... 370
   fg_drawellipse  -  НАРИСОВАТЬ ЭЛЛИПС  ............... 370
   fg_drawline fg_drawlinep  -  НАРИСОВАТЬ ЛИНИЮ  ...... 371
   fg_drawlineclip - ОТКЛИППИРОВАТЬ И НАРИСОВАТЬ ЛИНИЮ   372
   fg_drawmatrix  -  НАРИСОВАТЬ МАТРИЦУ  ............... 372
   fg_drawthickline  -  НАРИСОВАТЬ ТОЛСТУЮ ЛИНИЮ  ...... 373
   fg_fillbox  -  ЗАПОЛНИТЬ ПРЯМОУГОЛЬНИК  ............. 374
   fg_flush  -  ВЫТОЛКНУТЬ НА ДИСПЛЕЙ  ................. 374
   fg_getcolormap  -  ЧИТАТЬ ПАЛИТРУ (КАРТУ ЦВЕТОВ) .... 371
   fg_init  -  ИНИЦИАЛИЗИРОВАТЬ БЫСТРУЮ ГРАФИКУ  ....... 375
   fg_init_null - fg_init_vga12  -  ИНИЦИАЛИЗИРОВАТЬ FG  376
   fg_line_cpy  -  КОПИРОВАТЬ ЛИНИЮ  ................... 377
   fg_putc  -  ВЫВЕСТИ ЛИТЕРУ  ......................... 377
   fg_puts  -  ВЫВЕСТИ СТРОКУ  ......................... 378
   fg_readbox  -  ЧИТАТЬ РАМКУ  ........................ 378
   fg_readdot  -  ЧИТАТЬ ТОЧКУ  ........................ 379
   fg_restore  -  ВОССТАНОВИТЬ  ........................ 380
   fg_save  -  СОХРАНИТЬ  .............................. 380
   fg_setactivepage  -  УСТАНОВИТЬ АКТИВНУЮ СТРАНИЦУ ... 381
   fg_setcolormap  -  УСТАНОВИТЬ ПАЛИТРУ  .............. 381
   fg_setdisplaypage  -  УСТАНОВИТЬ ДИСПЛЕЙНУЮ СТРАНИЦУ  382
   fg_setlinepattern  УСТАНОВИТЬ ШАБЛОН ЛИНИИ  ......... 382
   fg_term  -  ПЕРЕЙТИ В РЕЖИМ А/Ц ТЕРМИНАЛА  .......... 383
   fg_writebox  -  ПИСАТЬ РАМКУ  ....................... 383


П Р И Л О Ж Е Н И Я


ПРИЛОЖЕНИЕ 1:  Zorlib  -  Библиотекарь  ................ 384

   Библиотекарь Zortech
      Что такое библиотекарь
      Использование Zorlib  ............................ 385
      Диалоговый режим Zorlib  ......................... 387
      Использование командных файлов
      Ресурсы
      Замечания


ПРИЛОЖЕНИЕ 2:  СООБЩЕНИЯ  ОБ  ОШИБКАХ  ................. 388

   Сообщения компилятора об ошибках
      ZTC1, ZTCPP1 и ZTC1B
      Ошибки в C++ расширениях
      Ошибки стандартного C  ........................... 391
      Сообщения об ошибках от редактора связей  ........ 399
      Сообщения об ошибках от Zorlib  .................. 404
         Предупреждения
         Сообщения об ошибках
         Системные ошибки  ............................. 405
      Сообщения об ошибках от MAKE
      Сообщения об ошибках от глобального оптимизатора   407
      Сообщения об ошибках времени исполнения  ......... 408


ПРИЛОЖЕНИЕ 3

   Переход от предыдущих версий Zortech C компилятора .. 409
      Общие блоки
      Литерные
      Модели памяти
      Предопределенные макросы  ........................ 410
      Препроцессор
      Арифметика над дальними указателями
      Измененные библиотечные функции
      Редакция связей  ................................. 411
      Интерфейс с языком ассемблера


ПРИЛОЖЕНИЕ 4  .......................................... 412

   Полная таблица кодов ASCII  ......................... 412






                           Часть 1

        Р У К О В О Д С Т В О  П О Л Ь З О В А Т Е Л Я
        ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД


                                               БЫСТРЫЙ СТАРТ
                                               ДДДДДДДДДДДДД

Кратко об установке

   Прежде, чем начать разрабатывать программы на C++ исполь-
зуя Zortech C++,  необходимо правильно настроить Ваши диски.
   Данное  руководство  по  быстрой  генерации предназначено
для пользователей, имеющих жесткие диски.
   За  более детальной информацией  по установке отсылаем  к
части 2,разделу:"Подробное руководство по установке системы".

   Установку  Zortech C++  на жестком диске  выполняет  файл
ZTCSETUP.EXE. При исполнении этой программы будет создан ка-
талог C:\ZORTECH и ряд подкаталогов.

   До запуска ZTCSETUP Вам нужно  сделать копию дистрибутив-
ных дисков и для инстолляции использовать эти рабочие копии.
В дальнейшем Вам  следует  хранить и дистрибутивы, и рабочие
дискеты в надежном месте.

   Для запуска ZTCSETUP  установите дискету #1 рабочей копии
системы в накопитель A:.  Если у Вас текущее приглашение  не
A>, то перейдите на него, набрав A: и затем нажав .

   Имея приглашение  A:>, наберите:

ZTCSETUP 

   Далее следуйте инструкциям на экране. По мере копирования
файлов с каждой дискеты Вас будут приглашать ставить следую-
щую  дискету. И, ставя ее,  Вы должны быть твердо уверены  в
том, что она является той, которая требуется.

   По окончании копирования дискет включите следующие строки
в конец Вашего файла AUTOEXEC.BAT:

SET PATH=C:\ZORTECH\BIN

(либо добавьте в строку PATH списка текущих маршрутов и
;C:\ZORTECH\BIN )

SET INCLUDE=C:\ZORTECH\INCLUDE
(В этом каталоге находятся включаемые файлы)

SET LIB=C:\ZORTECH\LIB
(В этом каталоге находятся библиотечные файлы)

   Если у Вас имеется RAM-диск (электронный диск, диск в до-
полнительной оперативной памяти),  то  можно  добавить также

SET TMP=d:

где d: - это имя накопителя RAM-диска. Кроме того,  рекомен-
дуется добавить в файл CONFIG.SYS следующие две строки:

BUFFERS=20
FILES=20

   Если Вам захочется,  чтобы контекстно зависимые подсказки
загружались  автоматически,  то  Вам  нужно  вставить в файл
AUTOEXEC.BAT следующую строку:

ZTCHELP

А теперь перезапустите машину для настройки нового окружения.


Кратко о редактировании

   Вход в редактор является простым, если система установле-
на с дистрибутива так, как описано выше.  Перейдите  в ката-
лог, в котором Вы хотите хранить исходные файлы, и наберите:

ZED 

   Вы войдете в редактор программ.  Если Вам хочется вызвать
редактируемый файл при входе в редактор, то используйте сле-
дующий альтернативный  синтаксис (если,  например,  Ваш файл
называется  MYPROG.CPP):  ZED  MYPROG.CPP  и  в этом случае:
если файл не существует, то он будет создан и открыт для ре-
дактирования; иначе откроется существующий файл.

   Теперь можно набирать Вашу С++ программу.

      Отметим,  что обычно  C++ файлы имеют расширение .cpp.
      Для таких файлов автоматически используется C++-компи-
      лятор, как и C-компилятор для файлов с расширением .c.
      Можно  принудительно  использовать  компилятор C++ для
      всех файлов, если воспользоваться флагом _cpp компиля-
      ции  (детали  см. в части 2:  Справочное руководство).
      Файлы заголовков (header files) для C++  обычно  имеют
      расширение .hpp.

   Запустите ZED согласно вышеприведенному  описанию и набе-
рите программу:

      #include 
      main()
      {
        cout << "Hello Bjarne!\n";
      }

проверьте правильность набора  и затем войдите в меню, нажав
Esc. Kлавишами со стрелками переместите подсвеченную полоску
на пункт Others  и нажмите  кл. Enter (или же просто нажмите
букву o [лат.]).  А теперь  таким же  способом из следующего
меню [подменю] выберите опцию cOmpile.
   Здесь  ZED  просит  задать  некоторые флаги [т.е. режимы]
компиляции либо другую информацию,  такую как дополнительные
библиотечные файлы.  Нажав F1,  Вы получите список имеющихся
опций,  а также их описание.  Если в поле ввода  уже имеется
какой-либо текст, то его можно удалить, нажав F9.  Окружение
запоминает флаги компилятора,  использованные  при последней
компиляции, и устанавливает их таковыми по умолчанию. Введи-
те флаг компилятора для компактной модели памяти, т.е.

-mc 

   Если пример набран правильно,  программа откомпилируется.
Если в процессе компиляции встретится ошибка,  то управление
возвращается редактору с позиционированием курсора на строке
с ошибкой.  Следует отметить,  что причина ошибки могла быть
выше этой строки, но сразу не была обнаружена анализатором.
   При успешном окончании компиляции Вам  выдается приглаше-
ние для ввода командной  строки  аргументов Вашей программы.
Нажимайте клавиши: Enter - для немедленного исполнения прог-
раммы,  Esc - для возврата в редактор.  Если Вы не сохранили
программу,  то в данной  точке Вам следует сделать это,  ис-
пользуя опцию FS.
   [Два способа сохранения файла:  После нажатия кл. Esc  Вы
попадете в меню режимов, здесь последовательно нажмите буквы
f, s - файл сохраняется, Вы остаетесь в системе  C++;  нахо-
дясь в редакторе,  нажмите две клавиши одновременно  Alt-v -
файл сохранится, и Вы переходите в DOS.
   Вариант первого способа: перемещение подсвеченной полоски
по элементам меню  при помощи клавиш со стрелками  и нажатие
кл. Enter на нужном элементе].
   В нашем примере  подобной проблемы нет;  Вы можете просто
нажать Enter для исполнения программы.  Вы увидите приветст-
венное обращение к Bjarne, а также приглашение нажать  любую
клавишу для возврата в  ZED.
   Итак,  Вы с помощью  Zortech C++ откомпилировали и испол-
нили Вашу первую программу.

   Выход из редактора тоже прост.  Нажмите клавишу  Esc  для
входа в режим меню, если Вы уже не находитесь в нем, и набе-
рите FX (что вызывает переходы Files,  eXit).  Выдается зап-
рос подтверждения необходимости сохранения  каждого изменен-
ного буфера.

   За более подробной информацией по компиляции и компоновке
C++-программ отсылаем к части 2: Справочное руководство.



                                            ВВЕДЕНИЕ  В  С++
                                            ДДДДДДДДДДДДДДДД

   Данное Руководство составлено в предположении,  что у Вас
есть опыт  работы  на языке C.  А если нет,  имеются  дюжины
подходящих книг.  Например, неплохо выбрать книгу  "C Primer
Plus", авторы  Waite, Prata, and Martin,   в которой имеется
глава по C++.
   Если Вы уже  знаете C,  то Вам  легко  будет подняться до
C++, поскольку нет нужды учить  весь язык сразу.  Вы сможете
программировать точно так же, как если бы Вы находились в C,
добавляя особенности C++ по мере их изучения.
   Имеются еще две книги, которые Вам стоит приобрести:
"An Introduction  to Object-Oriented Programming  and  C++",
авторы  Richard Wiener и Lewis Pinson (издательство Addison-
Wesley 1988), которая вводит C-программиста в C++ и содержит
ряд полезных примеров,  и "The  C++  Programming  Language",
автор Bjarne Stroustrup - создатель C++ (издана Addison-Wes-
ley 1986).  Эта  книга является "экспертным руководством" по
С++  и содержит много маленьких,  но искусных  и продвинутых
примеров.  Здесь рассматривается сложный материал, и она яв-
ляется "последним словом" по языку.  Обе книги  поставляются
фирмой Zortech.
   Две следующие главы предназначены для того, чтобы Вы про-
чувствовали язык  программирования  C++ и Zortech C++ в осо-
бенности и освоили бы  дополнительные  возможности,  которые
предлагает C++  по сравнению со своим  предшественником - C.
Они не претендуют на роль глубокого руководства,  и мы реко-
мендуем  Вам купить  одну  или  обе  упомянутые выше книги с
тем, чтобы Вы достигли профессионализма в языке. Книги можно
заказать в Zortech.


Объектно-ориентированное программирование (ООП)

   Цель объектно-ориентированного программирования - повыше-
ние производительности труда программиста. Язык помогает Вам
структурировать Ваши программы, а также переиспользовать код,
который Вы или кто-то другой  уже написали. Чем меньше рабо-
ты по написанию программы, тем выше Ваша производительность.
Объектно-ориентированные языки позволяют Вам создать  нечто,
называемое классом. Класс определяет новый тип данных. После
завершения  определения  класса компилятор  обрабатывает его
точно так же,  как если бы он был типом данных, встроенным в
язык подобно типу целого(integer) или чисел с плавающей точ-
кой (float).  Все,  что  требуется  сделать  для  класса как
встроенного типа, включая контроль ошибок,  выполняет компи-
лятор.  Описание новых классов  часто  называется  описанием
абстрактных типов данных.
   Если у Вас имеется некоторый класс, и Вам нужен несколько
отличный от него,  то не  требуется  возвращаться и изменять
класс.   Можно  просто  сказать:  "определить  новый  класс,
который  суть  старый  вышеописанный  класс  плюс  некоторые
изменения и дополнения, которые я хочу сделать". Это [перео-
пределение]  называется наследованием или порождением произ-
водного типа - Вы  "производите"  новый тип из  старого или,
другими словами, в новом классе "наследуете" свойства старо-
го.  Описание классов таким способом избавляет  Вас от массы
работы.
   Объектно-ориентированному  языку  требуется  больше,  чем
абстрактные типы данных и производные типы.  Если у Вас вна-
чале имеется единственный  класс,  часто называемый базовым,
и из  него  порождается  ряд  классов,  то  Вам  потребуется
управлять производными классами из базового. Например, пусть
базовый класс - shape  и порожденные: line, circle и square,
причем в каждом из них используются разные алгоритмы рисова-
ния.  Тем не менее, можно создать список из shapes (форм)  и
отрисовать (draw)  каждую из них  [по своему алгоритму],  не
зная,  что рисуется: круг, квадрат или прочее. Это свойство,
часто  называемое  "полиморфизмом" (commonality),  означает:
объект сам уточняет во время исполнения, что именно делать с
Вашим сообщением.  (Полиморфизм не возникает автоматически -
смотри пункт о виртуальных функциях).
   Вот краткое определение  ООП:

    Abstract Data Typing + Type Derivation  + Commonality
    ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД-
(Абстрактные типы данных + порождение производных типов +
                                                полиморфизм)
   Вы поймете смысл этих  терминов при изучении особенностей
языка. А пока запомните лишь, что C++ поможет Вам программи-
ровать более производительно.


   Эффективность

   В прошлом объектно-ориентированные языки были очень неэф-
фективными.  И хотя программист  пишет программы  достаточно
быстро, а на машине они исполняются все же медленно и требу-
ют больших ресурсов.  Например, в общем случае, нужно загру-
жать все окружение  разработки программы  при ее исполнении.
И это делает "солидную" программную поддержку громоздкой.
   Когда  Bjarne Stroustrup в Bell Laboratories  приступил к
созданию C++,  он отказался жертвовать скоростью и эффектив-
ностью использования памяти,  присущими C.  Он также заимст-
вовал присущий C "минималистский" подход: ядро языка включа-
ет возможности,  которых достаточно для создания всего того,
что можно только  вообразить. Если средства ядра Вам не под-
ходят,  то  Вы можете  самостоятельно "расширять" язык путем
создания новых классов.
   Итак,  C++  предоставляет  Вам  эффективный  по  скорости
исполнения  программ  компилятор наряду с его преимуществами
для разработки объектно-ориентированных программных систем.


Краткие предварительные сведения


   Объявления и описания

   Это на самом деле С,  но важно понять различие между опи-
саниями и объявлениями,  в  особенности,  когда  речь идет о
C++. Объявление - это сообщение компилятору.  Оно не генери-
рует объектного кода. Оно просто говорит:  "вот так выглядит
эта функция: ее имя, что она возвращает и стандартное  обра-
щение к ней. А сам код Вы увидите несколько позже." Объявле-
ние сообщает компилятору, что это не ошибка,  если Вы видите
вызываемую подобным образом функцию; ошибкой является,  если
функция  не вызывается  именно  таким  способом.  Вот пример
объявления:

double foo(int i, long j, float bar);

   В случае C, если Вы не объявили функцию до ее использова-
ния, то все нормально: компилятор предполагает, что она воз-
вращает тип int, и не контролирует передаваемые ей параметры,
так что Вы можете передавать любое количество параметров лю-
бого типа.  В случае C++ контроль типов  усилен.  Существует
мало  случаев, когда можно обойтись без  объявления  функции
до ее использования.  Описание  функции - это  код,  который
точно говорит, как работает функция.


   Прототипирование функций

   Обратите  внимание, что в приведенном выше примере задано
не только имя функции, но также и тип каждого из параметров.
Такой подход знаком программистам на  Паскале  и  называется
прототипированием функций.  Оно позволяет компилятору прове-
рять правильность вызова функции.  В случае C Вы не задавали
[типов] параметров при объявлении функции. А при обращении к
функции Вы могли бы передать ей любое количество  параметров
любого типа и компилятору до этого нет дела - это обуславлива-
ет все виды ошибок [передачи фактических параметров].  Новый
ANSI-стандарт  на C (и соответственно  Zortech C компилятор,
следующий стандарту) требует прототипирования функций.

   Зортеховский C++ выполняет автопрототипирование.  Если Вы
не описали функцию до ее использования,  то компилятор смот-
рит и определяет прототип при первом обращении к функции.


   Использование файлов-заголовков для объявления классов

   При создании нового типа данных Вы описываете класс в це-
лом:  имя нового типа данных,  какие данные он содержит, что
за функции работают с ним.  Такие  описания  классов  обычно
относятся в файл заголовков. Любой,  кто хочет  использовать
класс, просто включает (#include)  этот  заголовочный  файл.
Тем самым  компилятору  сообщается,  что класс существует, и
что можно с ним делать.  Если же Вы пытаетесь  делать что-то
некорректно, то компилятор Вам об этом сообщит.

   К примеру,  предположим,  что  имеется класс,  называемый
box, который Вы можете расписать (fill) тремя целыми,  а по-
том  опустошить  (empty).   Заголовочные  файлы  Zortech C++
обычно оканчиваются расширением .hpp и поэтому пусть заголо-
вочный файл box называется  box.hpp.  Ниже приводится пример
того, как можно использовать боксы:

   #include "box.hpp"
                  /* сообщает компилятору,  что такое box */
   main()
   {
     box B1, B2;              /* создадим несколько boxes */
     B1.fill(1,2,3);
     B2.fill(10,11,12);                    /* заполним их */
     B1.empty();
     B2.empty();                            /* очистим их */
   }

   Как здесь видно,  использование  кем-то описанного класса
весьма просто.

   Краткое введение в потоки

   "Потоки" (streams) - это заранее определенный набор клас-
сов для обмена с консолью и файлами. Они более естественны и
намного  легче в использовании,  чем  библиотечные функции в
просто C (хотя Вы можете, конечно,  продолжать использование
printf(), scanf() и т.п. - C++ не препятствует использованию
простых  C-функций).  В простом C стандартный ввод/вывод вы-
полняется с стандартными файлами: ввода-stdin, вывода-stdout
и файлом обработки ошибок-stderr.  В случае потоков им экви-
валентны cin,  cout и cerr ( и дополнительно cprn и caux для
принтера и дополнительных портов).

   Основная идея  состоит  в  следующем.  Имеется  несколько
объектов  для организации в программе  ввода/вывода.  И все,
что Вам нужно сделать, - это  отправить запрос к ним,  и они
сработают.  Для  работы с потоковыми объектами  используются
операции << и >>,которые имеют особый смысл в случае исполь-
зования с потоками (это называется совместным использованием
операций или  перегрузкой  операций  (Operator Overloading);
см. пункт  "Совместное  использование  операций".  Например,
пусть направляется несколько чисел для стандартного вывода :

   #include 
                       /* объявление потоковой библиотеки */
   main()
   {
     int a = 1, b = 2, c = 20;
     double pi = 3.14;
     cout << a;           /* выводит  значение  a;  можно
                          включать литералы и строки сов-
                                                   местно */
     cout << "b = " << b << "\n";
     cout <<"c должно быть = "<< 20 << "c = " << c << "\n";
                       /* что произойдет,  если выполнить
                                           все совместно? */
     cout <
   class OriginalWork {
      char author[20];
      char title[20];
      int month, day, year;
      int value;
   public:
         /*  во-первых, нечто, называемое "конструктором" */

      OriginalWork (char * Auth, char * name, int m,
                                      int d, int y, int val);
      void print();
      };             /* Существенно наличие точки с запя-
                             той после закрывающей скобки */

   Здесь мы подошли к понятию чего-то нового - конструктора.
Заметим, что имя конструктора - то же, что и класса.

   Компилятор вызывает конструктор, когда объект объявляется;
поэтому можно включить в конструктор код,  выполняющий авто-
матическую инициализацию. В нашем конструкторе окажется, что
все значения в объекте будут  инициализированы.  Запишем код
для OriginalWork в файле OWORK.CPP. Он подобен записи C кода
за исключением того, что:

   * каждое имя функции-члена должно быть связано с классом,
     для которого  она пишется, при  помощи  операции C++ ::

   * функции-члены имеют доступ к элементам структуры данных
     классов.

   #include "owork.hpp"
                 /* кавычки для файлов в текущем каталоге */
   #include 
                    /* углы для файлов в каталоге include */
   #include 
   OriginalWork::OriginalWork (char * Auth, char * name,
                               int m, int d, int y, int val)
   {
      month = m; day = d; year = y;
      value = val;
      strcpy(author, Auth);      /* обращение к C-функции */
      strcpy(title, name);
   }
   void OriginalWork::print()
   {
      cout << "name: " << title << "\n";
      cout << "Author: " << author << "\n";
      cout << "Created on: " << month << "/" << day << "/"
                                     << year << "\n";
      cout << "Value: $" << value << "\n";
   }

   Необычность конструктора  состоит в том, что Вам не нужно
говорить,  какое  значение  он  возвращает - компилятор  уже
знает это (это указатель на сам объект).

   Окончательно мы можем  использовать  класс  таким образом
(назовем этот файл MAIN.CPP):

   #include "owork.hpp"
   main()
   {
     OriginalWork painting("Bob Rembrandt",
                               "Blue Boy",5,24,65,74);
     OriginalWork photo(Eisenstadt", "Moon",6,30,77,2000);
     OriginalWork chapter("Bruce Eckel", "Intro to C++,
                                         5,24,88,0);
     painting.print();
     photo.print();
     charter.print();
   }

   Поскольку мы показали  эту  программу  в виде трех разных
составляющих (OWORK.HPP, OWORK.CPP и MAIN.CPP),  то Вам надо
откомпилировать  в  объектные  модули   файлы   OWORK.CPP  и
MAIN.CPP и скомпоновать их в итоговый  .EXE файл,  названный
ART.EXE, командой:

ZTC -oART.EXE MAIN OWORK

   При  этом  также  будут  сгенерированы   объектные  файлы
OWORK.OBJ и  MAIN.OBJ.  Вместо  этого  можно  собрать  все в
единственный файл ART.CPP и оставить команду:

ZTC ART

   Это может быть очень  удобно для небольших программ и для
их тестирования.  Однако, Вы увидите, что большинство проек-
тов будет содержать массу  классов,  находящихся в различных
кодовых файлах и файлах заголовков,  и многие из них уже от-
компилированы  в объектные  модули.  Большая часть работы по
организации программы просто состоит во включении файлов за-
головков  при использовании  классов  внутри  Вашей  главной
(main) процедуры и сборке всех объектных модулей, содержащих
откомпилированный код для классов.

   Заметим, что термин "объектный" использован здесь в исто-
рическом смысле,  а не в объектно-ориентированном:  исходный
код - это отправная точка,  а объектный код создается компи-
лятором и помещается в объектные  модули  откомпилированного
кода с расширением .OBJ. Эта терминология неудачна и вызыва-
ет путаницу,  но она была разработана до того,  как возникло
объектно-ориентированное программирование.

   Для создания программы, которая состоит из многих незави-
симо откомпилированных объектных модулей, Вам стоит написать
командный файл MS DOS (.BAT), в который включаются все необ-
ходимые команды.  Это должно  сокращать затраты на набор, но
не время: всякий раз, когда Вы создаете Вашу программу, весь
исходный  код  должен  быть  перекомпилирован  независимо от
того, изменялся он или нет. Существует более разумный способ
подобной организации:  см. главу Инструментарий, где описана
служебная программа make.



   Совместное использование функций (function overloading)

   В нашем втором полном  примере введем понятие совместного
использования функции (function overloading).  Это означает,
что у Вас может быть  много функций с одним и тем же именем,
но с разными аргументами, а компилятор будет выбирать подхо-
дящую функцию.  Это весьма хорошее свойство,  так как детали
остаются скрытыми, и Ваш код делается более легко читаемым.

   Вероятно, наиболее часто встречаемым примером совместного
использования функций являются конструкторы.  Обычно сущест-
вует несколько путей создания объекта.  Например, пусть соз-
дан класс,  названный  date;  он  может быть инициализирован
тремя целыми  числами,  строкой,  представляющей  дату,  или
вообще при отсутствии данных  (и в этом случае  используется
текущая дата).

   #include 
   class date {
      int month, day, year;              // месяц, день, год
   public:
      date();   /* нет начального значения - текущая дата */
      date(int m, int d = 1, int y = 88);
      date(char * datestring);
      date(date &);
      void print(char * msg = "");
   };

   Можно отметить  еще что-то новое:  во втором конструкторе
переменные d и y имеют  значения по умолчанию,  так что если
бы Вы скажете date birthday(12);  birthday автоматически бу-
дут заданы значения: d = 1 и y = 88. Вы также можете сказать
date birthday(11,5) или date birthday(12,5,87).  Значения по
умолчанию всегда должны быть последними значениями в списке.
Четвертый конструктор называется инициализацией копированием
(copy initializier).  Он является специальным и часто выска-
кивает там, где Вы его не ждете. Например, в описании

date celebration=birthday;,

инициализация копированием  вызывается  автоматически,  если
даже оператор и не выглядит как вызов этого конструктора ко-
торый должен бы появиться как date celebration(birthday);)

   Отсутствие инициализации копированием часто является при-
чиной проблем у начинающих. Она настолько важна, что следую-
щее определение C++ фирмы AT&T будет автоматически генериро-
вать инициализацию копированием,  если только Вы не написали
ее сами. Теперь рассмотрим код для класса date.


   #include "date.hpp"
   #include 
   #include                       /* для atoi() */
   date::date() {
      struct tm *t;
      time_t Ltime;
      time(&Ltime);
      t = localtime(&Ltime);
      month = t->tm_mon+1;
      day = t->tm_day;
      year = t->tm_year;
   }
   date::date(int m, int d, int y) {
                      /* отмечаем, что мы задали значения
                    по умолчанию лишь в объявлении класса */

   month = m; day = d; year = y;
   }
   date::date(char* datestring) {
      char buf[10];         /* временный буфер для кусков */
                       /* преобразует до тех пор, пока не
                                              разделитель */
      char * dt = datestring; char *bf = buf;
      month = atoi(dt);
      while(*dt != '/' && *dt != ':') dt++;
      dt++;                    /* движемся до '/' или ':' */
      day = atoi(dt);
      while(*dt != '/' && *dt != ':') dt++;
      dt++;
      year = atoi(dt);
   }

   date::date(date & otherdate)
   {
                            /* инициализация копированием */
   month = otherdate.month;
   day = otherdate.day;
   year = otherdate.year;
   }

   void date::print(char * msg) {
      cout <
   clase tuit {
      int a, b, c;
   public:
      tuit(int i=0, int j = 0, int k = 0)
      { a=i; b = j; c = k; }
                                /* см. "открытые функции" */
      tuit(tuit &);          /* инициализация копиpованием */
      tuit operator+(tuit &);
      tuit operator-(tuit &);
      tuit operator=(tuit &);
      void print(char * name = "");
   };

   tuit::tuit( tuit & othertuit) {
      a = othertuit.a; b = othertuit.b; c = othertuit.c;
   }

   tuit tuit::operator+(tuit & arg) {
      tuit result;
      result.a = a + arg.a;
      result.b = b + arg.b;
      result.c = c + arg.c;
      return result;
   }

   tuit tuit::operator-(tuit & arg) {
      tuit result;
      result.a = a - arg.a;
      result.b = b - arg.b;
      result.c = c - arg.c;
      return result;
   }

   tuit tuit::operator=(tuit & rvalue) {
      a = rvalue.a;
      b = rvalue.b;
      c = rvalue.c;
      return *this;
   }

   void tuit::print(char * name) {
      cout << name << ":";
      cout << "a = " << a << ", b = " << b <<
        ", c = " << c << "\n";
   }

   main() {
      tuit x(1,2,3), y(10), z(11,12);
      tuit u = x + y - z;
                          /* прелестно просто, не так ли? */
      x.print("x"); y.print("y"); z.print("z");
      (x+y).print(x+y);
      (x+y-z).print("x+y-z");
      u.print("u");
   }


   В этом примере имеются два места, которые могут поставить
Вас в тупик:  использование  '&'  и  ключевого  слова  this.
Смысл '&', по сути дела, тот же, что и в C: "адрес чего-то".
Вы можете  использовать  его,  как  могли  бы делать это в C
(если у Вас есть int c,  то Вы можете получить адрес c, ска-
зав &c). Однако,  в C++ использование '&' расширено - в при-
мере оно называется  ссылкой (reference). Значения поставля-
ются функциям и возвращаются  функциями "по ссылке". Это оз-
начает:  "Я передаю тебе  значение,  преврати  его в адрес".
Передача по ссылке часто  предпочтительна при передаче пара-
метров и возврате значений;  обычно она  повышает  эффектив-
ность.

   Ключевое слово this означает "адрес объекта,  в котором я
нахожусь".  Функции члены легко могут выбирать любой элемент
объекта просто по имени  элемента,  но  this  необходимо для
получения адреса объекта.  При совместном использовании опе-
раций всегда важно вернуть значение.  В случае operator+() и
operator-() оно совершенно  очевидно  (результат  операции),
но не является  таким  очевидным в некоторых других случаях,
подобных operator++() или operator=().

   Чтобы решить эту небольшую дилемму, помните, что Вы долж-
ны  уметь  использовать  операции  в  выражениях,   подобных
if (A++) и A=B=C.  Поэтому  результатом операции должен быть
сам объект: *this.  Отметим, что адрес  /this/  должен  быть
разименован до возврата результата; функция  объявлялась как
возвращающая  ссылку,  и ссылка  "ожидает",  чтобы  ей  дали
объект, а не адрес объекта.


Создание нового типа из старого типа

   Здесь  Вы  можете подумать, что требуется изрядно порабо-
тать при создании нового типа.  Так оно и есть,  ко времени,
когда Вы добавляли операции,  а также все другие хитрые воз-
можности.  Но  такая  концентрация  усилий  окупается  двумя
путями:

      1.   Получив  однажды  новый  тип как  отлаженный,  Вы
           всегда работаете с ним.  Его легко использовать в
           Вашей конечной системе, потому что компилятор га-
           рантирует  правильность  интерфейса и то,  что Вы
           используете его надлежащим образом.

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

   Посмотрим,  как это работает при  наследовании  из класса
OriginalWork.  Построим класс для более специфичной творчес-
кой работы:


   #include "owork.hpp"        /* объявляем базовый класс */
   class Painting : public OriginalWork {
                               /* наследует базовый класс */
      char style[30];  /* добавляем некоторые новые члены */
      char owner[30];
   public:
      Painting(char * artist, char * title, char * sty,
               char *own, int m, int d, int y, int val);
      void information();        /* говорит нам о картине */
   };


   Единственное различие между Painting (Живопись) и обыкно-
венным  определением  класса - это  "public: OriginalWork",
которое  говорит:  "этот   новый   тип   данных   создан  из
OriginalWork".   public  позволяет  производному (Coderived)
классу  Painting иметь доступ ко всем public элементам базо-
вого класса OriginalWork. Теперь определим функции члены:


   #include "painting.hpp"    /* где находится объявление */
   Painting::Painting(char * artist, char * title,
                      char * style, char * owner, int m,
                      int d, int y, int val)
        :   (artist, title, m, d, y, val) {
            strcpy(style,sty);
            strcpy(owner,own);
   }
   void Painting::information() {
      cout << "Painting:\n";
      print();
      cout << "Style : " << style << "\n";
      cout << "Owner : " << owner << "\n";
   }


   Здесь происходят две мудреные вещи:  вызывается конструк-
тор для базового  класса и происходит  обращение  к  функции
члену базового класса. Конструктор для базового класса вызы-
вается после имени функции и списка параметров и до открытия
фигурной скобки функции. Это обращение обозначено двоеточием,
подобно тому,  как  обозначен  наследуемый  класс в описании
производного класса.  Если Ваш базовый класс имеет совместно
используемые конструкторы,  то Вы  можете  вызвать  любой из
конструкторов,  просто  задавая  соответствующие  параметры.
В Painting::information(), мы вызвали print(), которая явля-
ется функцией-членом класса  OriginalWork.  Это так просто -
если функция существует в базовом  классе,  то Вы можете ис-
пользовать ее.  Ниже дается кое-что  для  упражнений с нашим
новым классом:


   #include "painting.hpp"
   main() {
      Painting Bull("Ralph Picasso", "Bull & Doves",
           "Abstract Expressionism", "Bend Art Museum",
           5,26,88, 495);
      Bull.information();    /* обращение к функции-члену */
      Bull.print();
                /* обращение к функции из базового класса */
   }


   Чтобы  показать,  как Вы можете  продолжать этот  процесс
бесконечно, создадим класс из Painting:

                                       /* Файл CUBIST.HPP */
   #include "painting.hpp"
   class Cubist : public Painting {
      int number_of_eyes;    /* ... на одной стороне лица */
   public:
      Cubist( char * artist, char * title, char * sty,
              int eyes, char * own, int m, int d,
              int y, int val);
      int eyes() { return number_of_eyes; }
   };
   Cubist::Cubist( char * artist, char * title, char * sty,
              int eyes, char * own, int m, int d,
              int y, int val)
      :   (artist, title, sty, own, m, d, y, val) {
          number_of_eyes=eyes;
   }
   #include "cubist.hpp"
   main() {
      Cubist Only("Bob Dega", "I Only Have Eyes...",
            "early", 3, "Bend Art Museum", 1,14,88, 196);
      Only.information();
      cout << "This was from the "<< Only.eyes()
                                  << " eye period\n";
   }

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

   eyes() написана  как  открытая  (in-line).  Это удобный и
эффективный способ определения очень коротких функций (смот-
ри in-line).

   Наконец, а что, если Вы не хотите  унаследовать класс, но
имеете объект этого класса в качестве члена структуры Вашего
класса? Например,  мы хотим  использовать наш класс date для
хранения начала и  конца  определенного  периода  творчества
художника. Наследование здесь не работает,  так как мы хотим
использовать  date  дважды.  Ответ  состоит  в использовании
объектов-членов:

   #include "cubist.hpp"        /* вышеприведенный пример */
   #include "date.hpp"          /* описание класса "date" */
   class CubistPeriod : Cubist {
      date beginning;
      date end;
   public:     /* Отметим, как вызываются базовый класс и
           конструкторы объектов до левой фигурной скобки */
      CubistPeriod(char * artist, char * title, char * sty,
              int eyes, char * own, int m, int d, int y,
              int val, char * start, char * finish)
          :   (artist, title, sty, eyesown, m, d, y, val),
              beginning(start), end (finish){}
          /* Нижеследующая функция, вероятно, больше, чем
                 следовало бы открытой (in-line) функции: */
      void All_info() { information();
         cout << "period starts: "; beginning.print();
         cout << "period ends: "; end.print();
      }
   };
   main() {
      CubistPeriod Dog ("Bob Dega", "Five-legged dog",
           "midlle", 2, "Bend Art Museum", 2, 24, 88,  399,
           "11/15/87", "2/25/88");
      Dog.All_info();
   }

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


По окончании базового курса

   Ну, вот Вы  и  прошли через  все  препятствия начального
курса по C++. У Вас достаточно образцов для того,  чтобы на-
чать писать свои собственные классы.  Когда Вы увидите,  как
легко это делается в C++, у Вас возникнут новые и более сме-
лые идеи и Вы захотите знать, как делаются вещи,  которые мы
Вам еще не показали.  Следующая глава открывает более глубо-
кие возможности C++.


Дальнейшая помощь в работе

   Как владелец Zortech C++,  Вы  начнете  получать  годовую
подписку Zortech C++  Newsletter,  как  только пришлете свою
регистрацию.  Журнал  содержит  советы  по программированию,
разные   хитрости  и  побочные   эффекты   при   пользовании
Zortech C++, а также информацию о новых релизах компилятора,
продуктах на C++ и другие полезные новости по C++.

   Если Вы не являетесь владельцем компилятора или Ваша под-
писка закончилась, то Вы можете получить ежегодник, отправив
32 доллара или 15.75  фунтов  стерлингов за одногодовую под-
писку шести двухмесячных выпусков по адресу:


Америка                               Европа

Zortech C++ Newsletter                Zortech C++ Newsletter
361 Massachussetts Ave                106-108 Powis St
Arlington MA 02174                    London SE18 6LU

   Если Вы предложите заметку,  которая будет опубликована в
следующем выпуске, то Вы получите годовую подписку и следую-
щую версию компилятора Zortech C++ бесплатно.















                                         БОЛЕЕ  СЛОЖНЫЙ  C++
                                         ДДДДДДДДДДДДДДДДДДД

   Этот раздел описывает некоторые из более глубоких возмож-
ностей языка.  Изложение материала не следует  рассматривать
как полный справочник, оно достаточно лишь для ознакомления.
Дальнейшие  подробности  можно  найти,  например,  в  книгах
Винера и Пинсона или Страустрапа.


Вызов функций-членов

   Как видно из предыдущего, если Вы имеете объект OBJ и хо-
тите вызвать одну из его  функций-членов  func(),  Вы просто
говорите OBJ.func().  Что,  если Вы определяете функцию-член
класса и хотите вызвать другую функцию-член класса? Когда Вы
находитесь внутри  функции-члена, всегда предполагается, что
Вы работаете с объектом, который еще не имеет имени - имено-
вание не появляется до тех пор,  пока объект не объявляется.
Для вызова  функции-члена  класса  из  другой  функции-члена
просто вызовите эту функцию без указания объекта, связанного
с ней, т.е.: func().


Константы

   Для создания константных  значений в обычном C Вы исполь-
зовали препроцессор,  например:  #define A 10.  К сожалению,
когда  препроцессор  завершается,  заменяя  каждое вхождение
A на 10,  компилятор не имеет  записи об A и не может выдать
Вам  какого-либо  сообщения с идентификатором A,  что значи-
тельно осложняет отладку программы.

   C++ включает  понятие  константы  (const),  const застав-
ляет  компилятор  контролировать и запрещать любую возможную
модификацию  значения.  В  приведенном  выше  случае:  const
int A=10. Константы намного более гибкое средство,  чем опе-
ратор #define;  они понимают 'область действия'  ('scoping',
смотрите   раздел   'Область  действия'),   можно   объявить
объект-константу  или передать константные параметры функци-
ям.  Zortech C++  транслятор может улучшить порождаемый код,
если он знает, что нечто является константой.

Комментарии

   C++  имеет  два типа  комментариев:  обычный  комментарий
C /* и */ и новый тип  комментария,  который продолжается до
конца строки:

int a = 4;       //комментарий только до конца этой строки


Многократные включения файлов-заголовков

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

   Общепринятым для предотвращения объявления  класса  более
одного раза  является использование препроцессора.  Это реа-
лизуется созданием специальной  переменной препроцессора для
каждого включаемого  файла.  В качестве имени переменной ис-
пользуется имя файла,  все буквы которого заглавные и не со-
держат символа '.' (ANSI C не разрешает использование симво-
ла '.'  в именах переменных).  Посмотрите  пример  для файла
"CHAIR.HPP":

      #ifndef CHAIRHPP
      #define CHAIRHPP
      class chair {        // объявление класса chair
      };
      #endif CHAIRHPP

   Объявление класса chair включается только, если  перемен-
ная CHAIRHPP не была ранее определена.


Область действия

   Правила области действия (scoping rules) определяют части
программы, где переменная действительна.  Эти части разделя-
ются открывающей и закрывающей фигурными скобками ({ и }).

   Чтобы увидеть, когда переменная выходит из области дейст-
вия (становится недействительной),  найдите ближайшую фигур-
ную открывающую скобку  перед  объявлением этой переменной и
затем  найдите  соответствующую ей закрывающую скобку. Пере-
менная  выходит  из  области   действия   после  прохождения
/при исполнении/ закрывающей скобки. Если переменная являет-
ся объектом некоторого класса,  то  при  выходе  из  области
действия будет вызван ее деструктор (если таковой определен).

   В обычном C все переменные должны быть объявлены в начале
области действия, сразу после открывающей скобки и перед лю-
бым оператором. В C++ Вы можете объявлять переменные в месте
их использования.  Подходящим  примером служит счетчик цикла
for :

      ...
      for (int i = 0; i<100; i++)
           for (int j = 0; j<100; j++)
                // здесь выполняется работа

      Заметьте, что можно объявлять и инициализировать пере-
      менную одновременно.


Открытые (inline) функции

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

   C++ объединяет лучшее из двух подходов  при помощи откры-
тых функций.  Объявляя функцию открытой, Вы заставляете ком-
пилятор заменить все вызовы функций кодом  открытой  функции
(как если бы Вы использовали препроцессор).

   Открытые функции обычно считаются единственными 'приемле-
мыми'  определениями для появления в файлах  заголовков. Они
должны быть краткими.  Открытые функции C++ должны использо-
ваться в местах,  где  в обычном C использовались  операторы
#define для замены небольшой  части  кода.  Примеры  будут в
следующем параграфе.


Функции доступа

   Обычно данные,  составляющие  объект  некоторого  класса,
объявляются как 'приватные' (private); это означает,  что Вы
не можете извлечь их и испортить за исключением случая, ког-
да программист  специальным образом дает Вам на это разреше-
ние (т.е.   Вы должны  использовать функции члены класса или
функции 'друзья').  Часто, однако, Вам нужно прочитать конк-
ретные значения из объекта.  Вместо  того,  чтобы делать эти
значения общими (что означает, что любой может их изменить),
лучше написать функции доступа, которые возвращают значение,
но не допускают изменения  извне  этого  значения в объекте.
Функции доступа являются,  возможно, наиболее распространен-
ным использованием открытого кода.

Пример:

      #include  // теперь можно использовать поток
      class insect {
         int legs;
         int eyes;
         int flight;
      public:         // все описанное выше приватно
                      // открытый конструктор
         insect(int l, int e, int f)
                    {legs=l; eyes=e; flight=f;}
                      // несколько открытых функций  доступа
         int number_of_legs() {return legs;}
         int number_of_eyes() {return eyes;}
         int   does_it_fly()  {return flight;}
      };
      main() {
         insect bug(7,9,1);
         cout << bug.does_it_fly();
      }

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


Динамическое распределение памяти

   Имеется два способа получения памяти в C++.  При объявле-
нии переменных им отводится место в стеке, продвижением вниз
указателя стека. Когда переменные выходят за область опреде-
ления, память из-под них освобождается автоматически, движе-
нием вверх указателя стека. Размер размещаемой в стеке памя-
ти должен всегда быть известен  во  время  компиляции.  Если
нужно создать переменную, размер которой неизвестен при ком-
пиляции, следует в программе  позаботиться об отведении этой
памяти в куче (heap),  называемой  также  свободной  памятью
(free store).  Кучу  можно  представлять  как занимающую дно
пространства памяти  программы и растущую вверх,  в то время
как стек занимает вершину и растет вниз.

   Можно  занимать и освобождать память в куче в любой точке
программы.  Важно  понять,  что размещаемая в куче память не
подчиняется правилам области определения,  в отличие от дру-
гих переменных (это полезная возможность - смотрите параграф
Ссылки).  Эти  переменные никогда не оказываются вне области
определения. Так что заняв память в куче, следует самому по-
заботиться  о  ее  освобождении.  Если  продолжать  занимать
память в куче,  не освобождая ее,  то программа (мистическим
образом) сломается. Большинство C пакетов имеют библиотечные
функции (например, malloc(), free()),  обеспечивающие работу
с динамическим отведением памяти,  но в C++ она,  как доста-
точно важная,  является частью языка.  C++ использует опера-
ции new и delete  для отведения и освобождения  динамической
памяти.  Аргумент  new - выражение,  задающее число байтов в
отводимой  памяти  (Это  выражение  состоит из имени типа и,
возможно, следующего за ним в квадратных скобках числа: чис-
ла элементов этого типа, которые нужно разместить.); возвра-
щаемое значение - указатель на начало блока памяти. Аргумен-
том delete является  начальный адрес блока  памяти,  которую
нужно освобождать (тот самый адрес, который  был  ранее пос-
тавлен new).  Предположим,  мы хотим, имея некоторые целые x
и y,  создать матрицу из  x  на  y  плавающих чисел (float);
тогда

   float * mat = new float[x*y];

разместит такую матрицу, а

   delete mat;

освободит память. Можно продолжать использование памяти пос-
ле ее освобождения или освободить ее более одного раза - оба
варианта являются ошибочными и могут  приводить к трудно об-
наруживаемым ошибкам.


Конструкторы и деструкторы

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

   Компилятор автоматически ставит обращение к соответствую-
щему конструктору при исполнении  описания и к деструктору -
при выходе объекта из своей области определения.
   Примеры  инициализации  включают  установку  переменных в
известные  значения,  отведение  памяти в куче,  копирование
значений из другого объекта и более необычные  работы,  свя-
занные со своеобразием  типов,  которые можно создать на C++
(например, рисование окна,  очищение очереди или инициализа-
ция последовательного порта).  Примерами очищения могут слу-
жить возврат памяти в куче, удаление окна с экрана и т.п.
   Для каждого класса  может  быть  несколько  конструкторов
(отличающихся  списками параметров)  но только один деструк-
тор. Деструкторы не имеют параметров.  Конструкторы имеют то
же имя, что и класс. Имя деструктора начинается с тильды (~),
за которой следует имя класса. Вот несколько примеров объяв-
лений конструкторов и деструктора:

   class matrix {                           //данные матрицы
   public:
      matrix();                         /* без параметров */
      matrix(matrix &);     /* инициализация копированием */
      matrix(int i, int j, int a);
      matrix(int i, int j, float a);
      ~matrix();                            /* деструктор */
                          // другие объявления класса matrix
      };

   Для простых классов  конструкторы и деструкторы не всегда
необходимы.  Если  класс  базируется  на стеке  (нет памяти,
отводимой  в куче),  не требует  инициализации  переменных и
передается функциям только по  ссылке  (передача по значению
требует инициализации копированием), то конструктор, вероят-
но, не нужен.
   Код конструкторов и деструкторов такой же, как и у других
функций  членов,  за  небольшими  исключениями.  Конструктор
автоматически возвращает  this  (указатель на объект;  через
этот указатель программируется инициализация и присваивание),
а деструктор не  возвращает  никакого  значения.  Не следует
указывать никакого  возвращаемого  значения ни в объявлениях
внутри класса, ни в описаниях этих функций.
   Обычно, когда объект создается,  сначала отводится память
под все  размещаемые в стеке переменные,  а затем вызывается
конструктор  (наоборот,  при выходе  за область  определения
сначала вызывается деструктор, если таковой был определен, а
затем освобождается память стека). Если, однако, Вы выполни-
ли в конструкторе присваивание переменной this, автоматичес-
кое отведение памяти в стеке подавляется (Вы должны понимать,
что делаете, прежде чем попробуете этот прием).


Ссылки

   Ссылка - это  указатель,  который  выглядит  как  объект.
Компилятор  сам  разыменовывает  его  (применяя операцию *).
Можно инициализировать ссылку другим  обектом (в этом случае
у Вас появится два способа работы с одним и тем же объектом,
что само по себе порождает  проблемы и должно использоваться
с осторожностью). Вот пример:

   foo A();                               // создается "foo"
   foo & B = A;
        // создается ссылка типа "foo", инициализированная A
   A.function();                   // это то же самое, что и
   B.function();

   В вышеприведенном фрагменте кода,  когда A выходит за об-
ласть определения,  для нее вызывается деструктор. Поскольку
B является ссылкой, для нее деструктор не вызывается никогда.
   Тот факт, что правило области определения /в части вызова
деструктора/  подавляется  для  ссылок,  может быть полезен.
Второй путь использования ссылок - создать объект  полностью
в свободной памяти и работать с ним через ссылку. Большинст-
во объектов располагается в стеке, кроме тех их частей, кото-
рые явно создаются при помощи new.  Однако,  можно создавать
эти объекты так,  чтобы они  целиком размещались в свободной
памяти (куче). Хороший пример - объекты данных, хранящиеся в
бинарном дереве.  Вообще говоря, не хотелось бы, чтобы куски
дерева разрушались просто от того, что они выходят за грани-
цы области определения.  Необходим  полный контроль над тем,
когда они добавляются к дереву и убираются из дерева.  В ка-
честве иллюстрации  рассмотрим  функции  add()  и remove() в
гипотетическом классе бинарных деревьев BinaryTree:

   void BinaryTree::add(int data) {
        // "leaf"(лист)  есть  некоторый  класс,  содержащий
        // данные и "прикрепляемый" к этому бинарному дереву
   leaf & newleaf = *new leaf(data);
        // Поскольку ссылка на нечто выглядит так же,  как и
        // это нечто, а не как указатель на него,  мы должны
           // разыменовать указатель, поставляемый операцией
                                         // new, сказав *new
   attach(newleaf);
   }
   void BinaryTree::remove(leaf & lf) {
         // "un_attach" удаляет "лист" из бинарного дерева и
                               // возвращает ссылку на лист:
   leaf & oldleaf = un_attach(lf);
         // для удаления ссылки (т.е. вызова деструктора для
                 // ссылки) следует привести ее к указателю:
   delete (leaf *)(&oldleaf);
   }

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

   void fred(foo & A) { A.member_function();} //используем А
   main() {
   foo B;
   fred(B); fred(&B);                    // вызовы идентичны
   }

   Если функция не модифицирует  своих параметров,  передача
по ссылке  предпочтительна как наиболее  эффективный  метод.
Это также простейший способ действий для начинающих. Если по
некоторым причинам Вам нужно модифицировать параметры (вмес-
то того, чтобы просто скопировать их в локальные  переменные
и модифицировать там), используйте передачу по значению.
   В этом случае  компилятор создает копию исходного объекта
(используя инициализацию копированием, которую Вы должны на-
писать). Это еще один непростой подход, которого начинающему
следует избегать.
   Последний прием с использованием ссылок - обойти механизм
защиты информации при помощи функции  доступа,  возвращающей
ссылку на фактическое  значение,  а не копию этого значения.
Примером того, где это полезно, является класс vector, в ко-
тором пользователь может изменить элемент вектора при помощи
операции [].

   #include 
   class ten_vector{
      int element[10];
   public;
      ten_vector(int x = 0) {    /* значение по умолчанию */
         for(int i = 0; i < 10; i++)
            element[i] = x;
      }
      int value(int i) { if (i < 10) return element[i];
                         else return 0; }
      int & operator[](int i) { return element[i]; }
   };
   main() {
      ten_vector V;
      cout << V.value(5);
                      /* можно читать, но не изменять его */
      V[5] = 20;             /* используется "operator[]" */
      cout << "  " << V.value(5);
   }

   Заметьте,  как симпатично это работает - поскольку компи-
лятор разыменовывает  адрес,  который поставляет operator[],
строка  V[5]=20  читается  совершенно  естественно.  Возврат
объекта из функции может оказаться непростым делом (смотрите
следующий параграф). В частности, нельзя пытаться возвратить
ссылку на локальную  переменную  (называемую также автомати-
ческой переменной).  Локальные переменные размещаются в сте-
ке - когда функция  завершится,  она возвратит ссылку на пе-
ременную вне области определения!


Совместное использование операций (Operator Overloading)

   Почти все операции в C++ могут совместно использоваться в
различных смыслах в зависимости от типов  данных,  к которым
они применяются.  Чтобы  правильно  работать с совместно ис-
пользуемыми операциями, надо понимать следующее.

      * При передаче аргументов в функции - операции следует
        использовать  ссылки,  и аргументы никогда не должны
        модифицироваться (Вы же не ожидаете, что A + B будет
        модифицировать A или B, не так ли?).
      * Хотя  разрешается  совместно  используемые  операции
        описывать как функции-друзья (friends) с двумя пара-
        метрами, предпочтительнее  (и менее запутанно) - де-
        дать их функциями-членами  с одним  параметром.  Для
        бинарных операций  this  при этом будет указывать на
        объект - левый операнд, а параметр - задавать правый
        операнд.
      * При  возвращении  объекта  из  функции-операции (или
        другой функции,  используемой в этом плане)  возврат
        следует выполнять значением.  Это значит, что должен
        быть  конструктор для инициализации  копированием; в
        случае, когда объекты имеют части в куче, это должно
        быть запрограммировано особенно тщательно, чтобы из-
        бежать порождения  мусора  (исключительно работоспо-
        собный метод, позволяющий избежать мусора, - подсчет
        ссылок, он демонстрируется в классе  String  в книге
        Строуструпа на странице 184).
      * При совместном использовании операций следите за тем,
        как они работают в выражениях произвольной сложности
        (A+B-C/D...). Пользователь, без сомнения, попытается
        сделать что-нибудь, о чем Вы и не думали.


Операция присваивания (operator=())

   Функция operator= по ряду  причин  необычна.  В простом C
присваивание возвращает  присваиваемое  значение,  благодаря
чему возможны  выражения  вроде  A=B=C,  но не для структур.
Неприятие в реализации не допускало множественное присваива-
ние структур.  C++ вылечил эту болезнь,  так что возвращение
объекта  после  присваивания  (при помощи  оператора  return
*this) допускает множественное присваивание объектов.

   Функция operator= не всегда используется там, где Вы это-
го ожидаете. Например:

                                       /* файл potato.hpp */
   class potato {
      int u, v;
   public;
      potato (int a, int b = 0) { u = a; v = b; }
      potato (potato & p) { u = p.u; v = p.v; }
      potato operator=(potato & p)
         { u = p.u; v = p.v; return *this; }
      };

                                         // файл potatst.hpp
   #include "potato.hpp"
   main() {
      potato X(1,2);
      potato y = potato(3,4);      // вызывается potato(3,4)
      potato Z = 5;                // вызывается potato(5,0)
      potato Q = X;           // вызывается potato(potato &)
      Y = Z;       // вызывается potato::operator=(potato &)
   }

   Обратите   внимание  на  использование  *this  в  функции
operator=().  Поскольку  operator=  возвращает значение типа
potato,  код return *this означает  "возврати  копию  самого
себя".

   Наконец,  при создании производного класса operator=() не
наследуется как все другие функции - она должна определяться
заново для каждого нового произвольного класса. Часто хочет-
ся использовать  operator=() из базового класса,  не набирая
ее заново.
   Вот как это сделать:

   #include "potato.hpp"
   class tomato : public potato {
      int t;
   public:
      tomato(int a, int b, int c) : (a,b) { t = c;}
      // заметьте, как вызывается инициализация копированием
                                      // из базового класса:
       tomato(tomato & rv) : (rv) { t = rv.t; }
       tomato operator=(tomato & x) {
          t = x.t;
          (potato)(*this) = (potato)x;
          return *this;
       }
    };
    main() {
       tomato A(1,2,3), B(4,5,6);
       A = B;
    }


Указатели на void

   Если объявить указатель на void, он будет содержать 'родо-
вой' адрес, который может быть приведен к адресу объекта лю-
бого типа.  Указатели на void используются при передаче ука-
зателей  функциям,  которые не могут знать тип передаваемого
им объекта,  а  также для передачи из функций  объектов,  не
имеющих типа.  Оба метода обходят контроль типов; их следует
избегать начинающим.


Виртуальные функции

   Виртуальная  функция - один из  ключевых  элементов в C++
как объектно-ориентированном языке.  Хотя язык может поддер-
живать абстрактные типы данных и наследование, он не являет-
ся действительно объектно-ориентированным,  если отсутствует
общность (commonality), называемая еще "полиморфизм". Вирту-
альные функции являются средством, обеспечивающим общность в
C++.

   Если  функция  объявлена в базовом классе как "обыкновен-
ная" (не виртуальная), она не полиморфная. Если при наследо-
вании из базового класса в новом классе функция  будет пере-
определена, получаются две отдельных функции.  Если, однако,
функция объявлена в базовом классе как virtual,  и переопре-
делена в классах, из него производных, то будет существовать
единственная функция  для  каждого  класса,  и функция может
быть вызвана для производного класса из базового класса.

   Что это значит?  Предположим,  мы строим оконную систему,
и существует три типа  объектов,  которые  можно  вывести на
экран  (назовем их ScreenObj):  Dialog (который пользователь
может вводить),  Reader (который пользователь может просмат-
ривать) и Message (который выводит сообщение и требует прос-
того ответа да-или-нет).  На экране может быть несколько по-
добных  объектов и все они управляются программой - менедже-
ром экрана.

   Менеджер экрана должен уметь открывать, закрывать, перед-
вигать и перерисовывать все выводимые объекты, независимо от
того, какого они конкретно типа. Чтобы обеспечить это, функ-
ции Open, Close,  Move  и ReDraw объявляются в базовом клас-
се   ScreenObj  виртуальными  и модифицируются в производных
классах.  Менеджер экрана просто хранит список из SreenObj и
вызывает подходящую функцию  для  каждого  элемента  списка.
Вот как это могло бы выглядеть:

   class SreenObj {                // здесь приватные данные
   public:
   virtual void Open(){} // функции должны иметь определение
   virtual void Close(){}     // в базовом классе (даже если
                                              // оно пустое)
   virtual void ReDraw(){}
   virtual void Move(int x, int y) {} // на какое расстояние
                                              // передвигать
   };
   class Dialog : public ScreenObj {
                     // здесь приватные данные класса DIALOG
   public:
      Dialog();                               // конструктор
      ~Dialog();                               // деструктор
      void Open(); void Close(); void ReDraw();
      void Move(int, int);
   };
   class Reader : public ScreenObj {
                     // здесь приватные данные класса Reader
   public:
      Reader();
      ~Reader();
      void Open(); void Close(); void ReDraw();
      void Move(int, int);
   };
   class Message: public ScreenObj {
                    // здесь приватные данные класса Message
   public:
      Message();
      ~Message();
      void Open(); void Close(); void ReDraw();
      void Move(int, int);
   };
   // Предполагается,  что  специализированные  для  классов
   // функции определены где-то еще (эта иллюстрация показы-
   // вает лишь схему работы).  Они выглядят как обычные эк-
                                          // ранные функции.

   class ScreenList {  // содержит список из ScreenObj_ектов
      struct Window {
         ScreenObj * head;            // приватная структура
         Window * next; }; // чтобы создать связанный список
      Window * head;                        // начало списка
      Window * current;  // Так мы можем двигаться по списку
   public:
      void add(ScreenObj &);          // добавление к списку
      void remove(ScreenObj &);   // удаление ScreenObj_екта
      void reset() { current = head; }
                               // переход на начало /списка/
      ScreenObj & GetNext();
       // возвращает ссылку на очередной ScreenObj из списка
   };
   main() {
      Message M; Reader R; Dialog D;
      Screenlist List;
      List.add(M); List.add(R); List.add(D);
      List.reset();
      while ( (ScreenObj & Win = List.GetNext()) != 0)
         Win.ReDraw();           // Перерисовать весь список
   }

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


Друзья (friends)

   Часто возникают  ситуации,  когда необходимо дать функции
не члену класса доступ к приватным элементам структуры клас-
са. Такой доступ может быть разрешен только самим классом, в
котором  функция  (или,  в некоторых  случаях,  целый класс)
объявляется как friend (друг) внутри объявления класса. Ниже
следует простой пример:

   class Integer {
   int X;
   public:
   Integer(int I) : X(I) {};
   friend void set(Integer &,int);
   };
   void set(Integer & A, int J) { A.X = J;}
                       // не функция член, но имеет доступ к
                                         // приватным данным

   Заметьте,  что в конструкторе для Integer вызывается кон-
структор  для объекта-члена класса X,  несмотря на то, что X
есть int (целое), т.е. встроенный тип.


Общие, приватные, защищенные (Public, Private, Protected)

   Ключевое слово public (общий, публичный) управляет досту-
пом к данным и функциям членам класса. Public разрешает дос-
туп всем.
   Винер  &  Пинсон   обсуждают  ключевые  слова  private  и
protected.  Они не были частью определения,  данного в книге
Строустрапа, и не поддерживались в Zortech C++ в момент пере-
дачи в печать этого руководства.  Однако,  в будущих версиях
Zortech C++ такая поддержка предполагается. Пожалуйста, про-
верьте файл read.me на втором дистрибутивном диске для полу-
чения более оперативной информации о новых возможностях.


Статические переменные

   В  Zortech C++ можно использовать  static (статические) и
глобальные объекты.  Статические  объекты подчиняются тем же
правилам области определения, за исключением того, что дест-
руктор не вызывается во время завершения функции, где описан
объект,  и объект не  "уходит"  в промежутках между вызовами
функции, как это происходит со "стековыми" (автоматическими"
переменными.

   Глобальные объекты объявляются вне всех функций и доступ-
ны из всех функций.  Конструкторы для статических и глобаль-
ных переменных вызываются до входа в main; деструкторы вызы-
ваются при обращении к exit(),  явном либо неявном, т.е. при
возврате из main().


Операция разрешения области действия

Операция разрешения области действия :: позволяет точно ука-
зать, какую функцию  нужно  вызвать,  в случаях,  когда есть
несколько вариантов,и умолчание-не тот вариант,что Вам нужен.
При  использовании  без префикса операция разрешения области
действия выбирает  глобальное  определение  или то,  которое
предопределено в языке (а не переопределенное для совместно-
го использования).  К примеру, можно переопределить ключевое
слово (операцию) для размещения в куче - new.  Чтобы выбрать
"нормальное" определение вместо  переопределенного,  следует
сказать

   ::new

   Переменные  также можно выбирать при помощи операции раз-
решения области действия:

   int A = 20;
   class deelybob {
      int A;
   public:
      deelybob() { A = ::A;
   };


Яндекс цитирования