Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Прикладное программирование на CC++ с нуля до мультимедийных и сетевых приложений

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
☆
Техника работы в С++ Builder 61
пасть в место текста, где находится функция-обработчик, достаточно во время работы с проектом сделать двойной щелчок по кнопке.
Внутри фигурных скобок в функции-обработчике можно запрограммиро­вать любые действия, которые приложение должно выполнить при нажатии на управляющую кнопку. Мы хотим, чтобы наша программа поздоровалась с окружающим миром при щелчке на кнопке. Самый простой способ — вывес­ти нужный текст в специальное окно сообщений. Поместим между фигурны­ми скобками слово ShowMessage. Что это такое? Это — некая новая конструк­ция, о которой мы пока ничего не знаем. Самое время воспользоваться систе­мой помощи, которую предоставляет нам Builder. Для вызова справки по любому служебному слову в программе достаточно установить курсор ввода в любое место на этом слове и нажать клавишу F1 на клавиатуре. Проделав эту операцию над словом ShowMessage, мы откроем окно помощи, представлен­ное на рис. 2.2.
Ðèñ. 2.2
В краткой аннотации мы читаем, что конструкция предназначена для вы­вода в окно сообщений текста и кнопки ÎÊ. Более подробная информация представлена в нижней части окна, а формальное объявление — в средней. Особенно вглядываться в формальное объявление не стоит. Нам нужно толь­ко установить, что после имени конструкции в круглых скобках должна сто­ять строка типа AnsiString. Этот тип — пример множества новых типов дан­ных, появившихся в языке С++ в дополнение к стандартным типам языка С. Заметим попутно, что многие имена типов в С++ просто являются псевдони­мами стандартных имен С. На самом деле часто это даже и не типы языка С++, а типы системы программирования WINDOWS — так называемой сис
-
62 Глава 2. Объектно-ориентированное программирование
òåìû API. Например, тип UINT — это не что иное, как обычное unsigned int. В нашем случае тип AnsiString мало чем отличается от обычного строкового типа. В этом можно убедиться, открыв ссылку Example в окне помощи и про­смотрев пример использования конструкции. В результате мы придем к выво­ду о том, что в скобках должна быть помещена обычная строка текста, взятая в кавычки. Именно этот текст и будет отображен в окне сообщений.
Вернемся к нашему главному текстовому модулю и допишем в фигурных скобках то, что требуется, допустив сознательно синтаксическую ошибку:
ShowMessage("Hello World!);
Ошибка заключается в том, что мы «забыли» закрыть кавычки справа. А сделали мы это для того, чтобы продемонстрировать реакцию системы на ошибку в программе. Давайте нажмем заветную кнопку F9. На этапе компи­ляции система начнет «ругаться» и в результате выдаст окно, представленное на рис. 2.3.
Ðèñ. 2.3
В верхней части окна отображена часть текстового модуля с выделенной строкой, в которой обнаружена ошибка. В нижней части окна дана расшиф­ровка ошибок. Обратите внимания на то, что компилятор ухитрился найти три ошибки, хотя на самом деле ошибка только одна — первая. Остальные ошибки называют наведенными. Из этого следует правило: сначала исправьте первую ошибку и, возможно, остальные исчезнут.
Итак, в качестве первой ошибки компилятор констатирует наличие неза­вершенной строки или символьной константы, и мы знаем, что компилятор в
Техника работы в С++ Builder 63
данном случае прав. Вторая ошибка заключается в отсутствии закрывающей скобки при вызове функции, и это, мягко говоря, не соответствует действи­тельности. То же самое следует сказать и о третьей ошибке — отсутствии сим­вола «;» в выражении. Наведенные ошибки!
Исправим ошибку, поставим в нужном месте закрывающие кавычки. Те­перь и компиляция, и линковка, и запуск программы должны пройти без ос­ложнений. В результате откроется окно созданной программы с кнопкой Button1. Когда вы щелкнете по кнопке мышью, появится окно сообщений с приветствием и кнопкой ÎÊ, показанное на рис. 2.4.
Ðèñ. 2.4
Совершенно очевидно, что все, что теперь можно сделать в программе, это нажать кнопку ÎÊ, и окно сообщений закроется. Далее остается только закрыть окно программы и поздравить себя с первым «самодельным» прило­жением.
Как мы с вами поняли, по умолчанию Builder создает проект для прило­жения, базирующегося на использовании формы. В ряде случаев использова­ние формы не является необходимым, а иногда и нежелательно. Рассмотрим разработку приложения без формы и, следовательно, без организации окна приложения.
Прежде всего, необходимо с помощью любого текстового редактора напи­сать текст, представленный в следующем листинге. Текст следует сохранить в рабочей папке будущего проекта под именем, например, Unit1.cpp.
#include <windows.h>
int PASCAL
WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpszCmdLine,
int nCmdShow)
64 Глава 2. Объектно-ориентированное программирование
{
MessageBox(NULL,"Привет","Без окна",MB_OK); return 0;
}
В любом файловом менеджере или проводнике Window перейдите в папку и сделайте двойной щелчок мышью по этому файлу. Предполагается, что файлы с расширением .ñðð связаны с Builder'îì. Builder загрузит файл и пред­ложит создать проект для приложения, с чем следует согласиться. Далее обычным образом клавишей F9 нужно запустить обработку проекта — компи­ляцию, линковку и запуск. В результате будет создан и выполнен исполняе­мый файл программы, и на экране вы увидите то, что показано на рис. 2.5.
Ðèñ. 2.5
Что же мы здесь имеем? Обратимся к листингу. Прежде всего, отметим, что для всех приложений Windows, а именно с такими программами мы и ра­ботаем, практически всегда требуется подключение заголовочного файла
windows.h. Далее, если мы не используем форму, то есть отходим от Builder-проекта по умолчанию, то необходимо использовать главную функ-
öèþ WinMain. Это — аналог функции main в языке С. С нее начинается вы­полнение программы, а у нас она вообще единственная. В наши задачи пока не входит подробно знакомить читателя с синтаксисом тех или иных конст­рукций языка. Поэтому примите оформление функции WinMain в листинге в качестве «истины в последней инстанции», а если это вас не устраивает (и это прекрасно!), то читайте документацию. Укажем только, что функция име­ет целый тип и, поэтому, последним выражением имеет оператор возврата return 0, хотя это возвращаемое значение нигде не используется.
Внутри функции WinMain мы вольны делать все, что нам захочется. А за­хотелось нам создать приветствие, но немного отличающееся от приветствия в первой программе. Для этой цели мы использовали функцию MessageBox. Если вы посмотрите в справку по этой функции, то увидите, что первым аргу­ментом у нее должен быть указатель порождающего окна, а поскольку у нас такового нет, мы и поставили здесь NULL. Второй аргумент — текст, выводи­мый в окно сообщения. Здесь все ясно. Третий аргумент — текст в заголовке окна, что также не требует пояснений. Последний аргумент содержит систем­ную константу, определяющую, что еще будет в окне. В данном случае в окне будет еще кнопка ÎÊ, которая закрывает как само окно сообщения, так и всю программу.
Большинство приложений, создаваемых в Builder'е, могут иметь в своей основе окно, задаваемое формой так, что именно такая конфигурация нового
Техника работы в С++ Builder 65
создаваемого проекта предлагается по умолчанию. Огромное упрощение раз­работки программ достигается с помощью размещения на форме так называе­мых визуальных компонентов (VC), уже упомянутых и использованных в пер­вой программе. Несомненно, и мы в дальнейшем будем использовать визуаль­ные компоненты в нашей работе, в связи с чем необходимо поговорить об этих инструментах более подробно.
По сути дела VC являются объектами специализированных классов, ин­капсулирующих в себе свойства (properties) и методы (methods). Кроме того, к членам классов визуальных компонентов следует отнести так называемые со­бытия (events) — «происшествия», случающиеся с VC. Главной особенностью этих специальных классов является то, что объекты VC обычно отображаются в окне формы в виде разнообразных визуальных конструкций: кнопок, полей ввода данных, полей выбора и многих других «картинок», которые мы видим при работе готовых программ в Windows. Как это ни парадоксально звучит, но существуют и не визуальные VC. Эти объекты не отображаются в окнах рабо­тающих программ, а используются именно при разработке приложений. Вот со всеми этими премудростями нам сейчас и предстоит вкратце познакомить­ся. По-прежнему не будем излагать материал последовательно и скрупулезно, а проиллюстрируем все необходимое примерами.
Поставим себе следующую задачу. Необходимо разработать программу, которая при запуске открывает окно, представленное на рис. 2.6.
Ðèñ. 2.6
Здесь имеются две надписи, поле ввода числового значения и одна кноп­ка. В открывшемся окне мы должны иметь возможность изменить или оста­вить предложенным по умолчанию число. После нажатия кнопки ÎÊ про­грамма должна просто завершить свою работу, закрыть окно по истечении времени, указанного в поле ввода.
Создадим новый проект с формой, а это мы уже умеем делать, предвари­тельно подготовив папку для проекта. Сохраните пока пустой проект. Помес­тите на форму визуальный компонент Label (метка) со вкладки Standard биб­лиотеки VCL. Этот компонент обозначен большой буквой À. Как только вы положили VC на форму, он отобразится в окне инспектора объектов (Object Inspector) слева от формы. Здесь будет открыта вкладка свойств объекта Properties. Â ïîëå Caption сейчас написано Label1. Замените надпись на ÇÀ-
66 Глава 2. Объектно-ориентированное программирование
КРЫТЬ ПРОГРАММУ ЧЕРЕЗ. Текст в метке на форме соответственно изме­нится. Метку можно перемещать по форме, захватив ее мышью. Передвиньте компонент ближе к верхнему левому углу. Если после этого метка перестала отображаться в инспекторе (и там стала отображаться форма), просто снова щелкните по ней мышкой. Активизируйте свойство Color и по стрелке справа выберите цвет фона. Мы сделали его белым. Поместите правее метки компо­нент Edit с той же вкладки Standard. Свойство Text замените на 5000. Правее только что созданного поля редактирования поместите еще одну метку с тек­стом МИЛЛИСЕКУНД и тоже белым фоном. На этом этапе можно прове­рить, все ли у нас в порядке. Сохраните проект и запустите его на исполне­ние. У вас должно появиться окно с отображением созданных элементов. За­кройте его.
Со вкладки System библиотеки визуальных компонентов возьмите таймер (Timer) и разместите его на форме. Таймер работает следующим образом. Как только он становится доступным, то есть как только его свойство Enable ста­новится ИСТИНОЙ (true), начинается отсчет времени. После того как прой­дет столько миллисекунд, сколько задано в свойстве таймера Interval, наступа­ет событие OnTimer, реакцию на которое нужно запрограммировать. Таким образом, установите свойство таймера на вкладке Properties инспектора объ­ектов в false (ЛОЖЬ) — сначала таймер должен быть заблокирован. Перейдите на вкладку событий (events) и сделайте двойной щелчок мышью по пустому полю правее названия события OnTimer. Сразу же откроется главный тексто­вый модуль программы, где тут же сформируется функция — обработчик со­бытия. Тело функции пока пусто. Здесь мы должны написать выражение, за­дающее реакцию на событие. Реакция очень проста — закрыть программу. Для этого можно, например, вызвать функцию exit(1). Теперь обработчик со­бытия в текстовом модуле должен выглядеть следующим образом:
void __fastcall TForm1::Timer1Timer(TObject *Sender) {
exit(1);
}
На следующем этапе разместим на форме кнопку, изменив название (свойство Name) с установленного по умолчанию Button1 íà ÎÊ — â ïîëå Name напишите ÎÊ и нажмите Enter. Теперь необходимо написать обработ­чик события OnClick щелчка по кнопке. Это, конечно, можно сделать через инспектор объектов, но для основного события объекта, а для кнопки щел­чок — это основное событие, можно поступить проще. Сделайте двойной щелчок по кнопке на форме, и вы сразу попадете в текстовый модуль, в функцию-обработчик, которая тоже пока пуста.
Что необходимо написать в обработчике? Сначала нужно задать интервал срабатываний таймера. Этот интервал, выраженный в миллисекундах, необхо­димо взять из поля редактирования и присвоить соответствующему параметру таймера. Напомним, что параметр Interval является свойством объекта Timer1, а текст в поле редактирования является свойством Text объекта Edit1. Казалось бы, что для достижения поставленной цели нужно применить выражение при
-
Структуры 67
сваивания Timer1->Interval = Edit1->Text;. Если мы вставим это выражение в обработчик и попробуем скомпилировать программу, то получим ошибку:
[C++ Error] Unit1.cpp(26): E2034 Cannot convert 'AnsiString' to 'unsigned int'.
Компилятор сообщает вам, что не может превратить выражение типа строка в выражение типа беззнаковое целое. Действительно, если вы обрати­тесь к справке по конструкции Interval для таймера и конструкции Text для поля редактирования, то увидите, что эти величины разного типа. Дело по­правимое. Для конвертирования строки в целое существует специальная функция StrToInt, и если в обработчике написать
Timer1->Interval = StrToInt(Edit1->Text);
то все будет в порядке.
Далее в обработчике щелчка по кнопке следует запустить таймер — при­своить свойству Enabled значение ИСТИНА (true). Окончательно функ­ция-обработчик должна выглядеть следующим образом:
void __fastcall TForm1::OKClick(TObject *Sender) {
Timer1->Interval = StrToInt(Edit1->Text); Timer1->Enabled = true;
}
Теперь все готово к запуску программы. Сделаем это. Возможно, не лиш­ним будет отметить, что после запуска приложения в поле редактирования значение 5000 миллисекунд, заданное нами по умолчанию, можно заменить на любое другое.
На этом изготовление программы заканчивается. Можно немного «навес­ти красоту». Захватив мышкой рамку формы слева или справа, снизу или сверху, можно изменить размеры окна формы и привести их к виду, показан­ному на рисунке. Вместо безликого form1 можно задать имя окна формы че­рез свойство Caption в инспекторе объектов. Наконец отметим, что таймер яв­ляется тем самым не визуальным VCL-компонентом. При разработке он при­сутствует на форме, при исполнении программы он не виден.
Структуры
Для объединения однотипных данных (именно переменных заданного типа) в языке С используются массивы. Существует средство объединения по какому-то признаку и элементов различных типов. Такие средства полу­чили название структур. Вообще говоря, без использования структур в боль­шинстве программ можно было бы безболезненно обойтись. Однако при пе­реходе к языку С++ знакомство со структурами становится крайне жела­тельным, поскольку от понятия структуры можно наиболее естественным образом перейти к фундаментальному понятию объектно-ориентированного
68 Глава 2. Объектно-ориентированное программирование
программирования — понятию класса. Кроме того, в практике программи­рования структуры используются на удивление широко. Типичный пример: программирование записи, обработки и воспроизведения звука и изображе­ний средствами Windows практически полностью основывается на использо­вании структур.
Формальное описание структуры как типа данных имеет следующий вид:
struct [Òåã] {
Объявления элементов структуры;
} [Переменные структуры];
Служебное слово struct означает, что объявлена структура. Необязатель­ная (в связи с этим взятая в прямые скобки) конструкция Òåã является име­нем типа структуры. При декларации в программе конкретной переменной структуры Òåã будет выступать в роли имени типа (как int, long и прочее). В фигурных скобках помещаются описания членов структуры, называемых также элементами и полями. Описания полностью совпадают с описаниями переменных в программе, например, double s; int a[12]; char *sss и так далее.
Само по себе объявление типа структуры не создает соответствующих пе­ременных. Введение в программу переменной структуры может быть выпол­нено двумя способами. Во-первых, переменную можно объявить стандартным образом. Пусть описан тип структуры:
struct NewStr {
int a,b; double c;
};
Тогда в функции, работающей с данной структурой, может быть задана следующая конструкция:
NewStr A,*B,C[4];
Здесь описана переменная структуры À, указатель на переменную струк­туры B и массив из четырех переменных структуры Ñ описанного типа.
Во-вторых, объявление переменных структуры можно сделать сразу при декларации типа структуры. В этом случае та же конструкция A,*B,C[4] поме­щается после закрывающей фигурной скобки. При этом тег структуры зада­вать не обязательно.
Обращение к членам структуры в программе выполняется с помощью разделителя «.» (точка) или разделителя «->» (стрелка). Если обращение вы­полняется через имя переменной структуры, то используется первый вариант. Так, в нашем примере для присвоения значения члену b числового значения можно применить выражение присваивания:
A.b = 7;
Структуры 69
Поскольку у нас объявлен указатель на структуру Â, аналогичное выраже­ние присваивания будет выглядеть так:
B->b=7;
Теперь рассмотрим небольшой пример, типичный для работы со структу­рами. Определим структуру, в которой будут содержаться данные на десяте­рых сотрудников отдела некоторой организации. Данные представляют собой порядковый номер сотрудника — целое значение num, фамилия, записанная в строке — символьный массив name, возраст — целая переменная age, пол — символьный массив из одного элемента sex, в который заносится бук­ва f èëè m. Очевидно, все перечисленные элементы в свою очередь являются элементами массивов длиной 10 по числу сотрудников.
#include <stdio.h> #include <conio.h> #include <string.h>
struct BASE { int num[10]; char name[10][24]; int age[10]; char sex[10][1]; };
void main(void)
{
BASE bas1,bas2; int i; FILE *f1; clrscr(); bas1.num[0]=0; strcpy(bas1.name[0],"Ivanov"); bas1.age[0]=44; strcpy(bas1.sex[0],"m"); f1=fopen("C:\ivb\ppis\bas1f.txt","wb"); fwrite(&bas1,sizeof(bas1),1,f1); fclose(f1); f1=fopen("C:\ivb\ppis\bas1f.txt","rb"); fread(&bas2,sizeof(bas1),1,f1); puts(bas1.name[0]); fclose(f1); getch();
}
В приведенном листинге объявлен тип структуры BASE и в главной функ­ции созданы два экземпляра структуры bas1 è bas2. В программе инициализи­руются поля для первого (точнее — нулевого) сотрудника с номером 0, фами­лией Ivanov, возраст 44 года, пол мужской. Остальные девять «строк» в струк­туре остаются не инициализированными. По некоторому пути в файловой системе открывается для записи двоичный файл с именем bas1f.txt. Расшире­ние txt не должно вводить читателя в заблуждение. Мода «wb» функции от
-
70 Глава 2. Объектно-ориентированное программирование
крытия файла fopen определяет то, что файл именно двоичный и открыт для записи. Нетрудно видеть, что в указанный дисковый файл целиком копирует­ся структура bas1. Далее файл закрывается и вновь открывается уже для чте­ния. Содержимое файла копируется в экземпляр структуры bas2, и из этой структуры извлекается и выводится на экран фамилия пользователя. При пра­вильной работе программы должно быть напечатано, естественно, слово Ivanov. Наверное, нет нужды подробно пояснять, что здесь представлена «за­готовка» работы со структурой в форме некоторой базы данных — ее созда­ние, изменение и сохранение на диске в виде файла.
Классы
Понятие класса является ключевым и основополагающим понятием объ­ектно-ориентированного программирования (ООП). С другой стороны, это понятие является логическим продолжением и расширением понятия струк­туры, с которым оперируют и не объектно-ориентированные системы. Также как и структуру, класс с полным основанием можно рассматривать как новый тип данных. Переменные такого типа как раз и являются теми самыми объек­тами, которые и дали название ООП.
Переход от структуры к классу, как расширение структуры, в первую оче­редь связано с возможностью включения в класс кроме переменных-членов еще и функций-членов. В современной литературе по ООП принято называть функции-члены методами класса, а переменные-члены — свойствами класса. Вторым важнейшим отличием от структуры является то, что члены класса (как переменные, так и функции) могут быть либо открытыми, либо закрыты­ми. По умолчанию все члены класса являются закрытыми. Это означает то, что оперировать с закрытыми данными могут только собственные методы класса. Если же необходимо получить доступ к свойствам извне (например, из главной функции программы), то свойства должны быть объявлены открыты­ми с помощью ключевого слова public:. Разумеется, для обеспечения возмож­ности вызова функций-членов извне необходимо эти методы также объявить открытыми.
В простейшем виде синтаксис объявления класса может выглядеть сле­дующим образом:
class имя-класса {
// Объявления закрытых членов класса public: // Объявления открытых членов класса
}[Объекты] ;
Формально имя класса может быть опущено, аналогично тегу структуры. На практике же имя задается практически всегда. Также, аналогично структу­рам, после закрывающей фигурной скобки может быть сформирован список объектов класса — по именам или указателям. При этом сразу при объявле-