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

ООП_Лабораторный практикум

.pdf
Скачиваний:
79
Добавлен:
11.05.2015
Размер:
1.5 Mб
Скачать

зайти в меню File->Current, то появится окно сообщения показывающее то число, которое введено в окне редактирования.

При запуске программы, главное окно должно будет выглядеть так (рис 5.1. ):

Рис 5.1. Главное окно лабораторной программы №5

Создайте диалоговый проект со следующими параметрами:

Project Name - Speed.

Please enter title of your dialog - The Speed Program.

2.Создание меню программы Speed

Для того, чтобы создать меню программы зайдите в закладку Resource View, раскройте там пункт Speed Resources, затем щелкните на правую кнопку мыши .

В раскрывшемся контекстном меню Выберите пункт Insert..., появиться диалоговая панель (рис 5.2):

Рис. 5.2 Панель Insert Resource

Выберите здесь Menu и нажмите на кнопку New для создания нового меню. Затем зайдите в пункт Menu, в закладке Resource View, и нажмите на IDR_MENU1 справа в окошке появиться окно визуального проектирования меню. Оно будет выглядеть так:

41

Рис. 5.3 Вид созданного пустого меню

Вы видите в левом верхнем углу этого окна небольшой прямоугольник, этот прямоугольник является областью для ввода названия пункта меню. Нажмите на него мышкой, затем нажмите на правую кнопку мыши и в появившемся контекстном меню нажмите на Properties, а в раскрывшемся диалоговом окне:

5.4 Окно свойств верхней строки меню

Задайте заголовок пункта меню в Caption - &File, первй значек &, подчеркивает первую букву F слова File, это означает, что при нажатии на клавиши ALT+F всплывет пункт меню File. Нажмите Enter, в прямоугольнике появиться File, ниже откроется еще одно окошко с прямоугольником, в этом прямоугольнике вы уже будете задавать названия пунктов меню File. Выделите мышкой этот прямоугольник, раскройте контекстное меню Properties, и в раскрывшемся окне задайте в Captions название пункта меню &Сurrent Speed и нажмите Enter.

Теперь опять зайдите в Properties, можно использовать комбинацию клавиш

ALT+ENTER, и посмотрите в ID, вы увидите там запись ID_FILE_CURRENTSPEED - это интендификатор пункта меню Current Speed, с помощью него вы сможете связывать этот пункт меню с событиями. Этот идентификатор Viusal C++ сгенерировал сам.

Ниже включите еще один пукнт с названием &Exit, для выхода из программы.

Далее создайте меню Help. Спроектируйте его так, как показано на следующем рисунке:

5.5 Вид меню Help программы

Теперь, когда меню визуально спроектировано, его надо связать с диалоговой панелью, для этого меню вы добавите в класс диалоговой панели. Для этого Выберите мастер ClassWizard в меню View, в ответ Visual C++ выведет вам диалоговою панель Adding a class(добавление класса):

42

Рис 5.6. Окно добавления нового класса в проект

Выберите здесь Select an existing class(выбрать уже существующий класс), это значит, что вы хотите включить меню уже в существующий класс, нажмите на кнопку OK. Раскроется еще одно окно Select Class(выбрать класс), выберите класс CSpeedDlg, отвечающий за диалоговую панель, не оставляйте установки по умолчанию!

Рис 5.7. Окно выбора класса, ассоциирующегося с ресурсом

Нажмите на кнопку Select.

3.Визуальное проектирование диалоговой панели

Расставьте элементы управления как показано на рис. 4.1 и согласно таблице 4.1. Таблица 4.1. Оконные элементы программы.

Объект

Свойство

Установка

Dialog Box

ID

IDD_SPEED_DIALOG

 

Caption

The Speed Program

 

Menu

IDR_MENU1

 

Font

System, Size 10, страница Styles

Static Text

ID

IDC_STATIC

 

Caption

Speed:

Edit Box

ID

IDC_SPEED_EDIT

4.Связывание событий с элементами управления

Свяжите переменную с окном редактирования.

1.Выберите ClassWizard в меню View

2.Выберите закладку Member Variables в панели ClassWizard

43

3.Щелкните на кнопку Add Varible и задайте переменную следующим образом: Varible Name: m_SpeedEdit

Category: Value Varible Type: int

4.Щелкните на кнопку OK.

5.Переменной типа int m_SpeedEdit можyj задать максимальное и минимальное значение этой переменной. Задайте в Maximum Value значение 100, это значит, что вы сможете задавать значение переменной в интервале от 0 до 100.

6.Щелкните на кнопку OK диалоговой панели ClassWizard.

Связывание кода с событием EN_CHANGE окна редактирования

Используйте диалоговую панель ClassWizard для выбора следующего события: Class Name: CSpeedDlg

Object ID: IDC_SPEED_EDIT Messages: EN_CHANGE

Код для функции OnChangeSpeedEdit():

void CSpeedDlg::OnChangeSpeedEdit()

{

//TODO: If this is a RICHEDIT control, the control will not

//send this notification unless you modify CDialog::OnInitDialog()

//function to send the EM_SETEVENTMASK message to the control

//with the ENM_CHANGE flag ORed into the lParam mask.

//TODO: Add your control notification handler code here

////Мой код начинается здесь////

//Обновить экран

UpdateData(TRUE);

////Мой код заканчивается здесь////

}

Связывание кода с пунктом CurrentSpeed меню File

Событие COMMAND возникает при выборе пункта меню, в данном случае при выборе пункта Current Speed. Чтобы связать код с событием COMMAND, выполните следующие действия:

1.Откройте закладку Resource View, раскройте пункт Speed View, а там выбирите Menu. Выполните двойной щелчок по IDR_MENU1.

2.Выберите ClassWizard в меню View

3.Выберите закладку Message Maps в панели ClassWizard

4.Используйте диалоговую панель ClassWizard для выбора следующего события: Class Name: CSpeedDlg

Object ID: ID_FILE_CURRENTSPEED Messages: COMMAND

5.Щелкните на кнопку Add Fucntion и в раскрывшемся окне нажмите кнопку OK.

6.Нажмите кнопку Edit Code и напишите следующий код в функции

OnFileCurrentspeed():

void CSpeedDlg::OnFileCurrentspeed()

{

// TODO: Add your command handler code here

////Мой код начинается здесь////

char strSpeed[100];

44

itoa(m_SpeedEdit,strSpeed,10); MessageBox(strSpeed);

////Мой код заканчивается здесь////

}

Первые два оператора, преобразуют в строку целое значение, хранящееся в переменной m_SpeedEdit:

char strSpeed[100]; itoa(m_SpeedEdit,strSpeed,10);

Последний оператор использует функцию MessageBox() для вывода значения строки,

хранящееся в переменной strSpeed: MessageBox(strSpeed);

Упражнение 1. Модифицируйте программу так, чтобы при выборе пункта меню File->Exit программа завершала работу.

Упражнение 2. Модифицируйте программу так, чтобы при выборе пункта меню Help->About программа выводила стандартную диалоговую панель About.

Подсказка: CAboutDlg dlg; dlg.DoModal();

Упражнение 3. Расширьте возможности программы Speed, включив новый пункт Say Hello в меню Help, чтобы при его выборе появлялась панель сообщения Hello!

Часть 2. Работа с динамической строкой и перегрузка операций

Напомним, что работа со строками в языке Си реализована путем использования одномерных массивов типа char, т.е. строка символов - это одномерный массив типа char, заканчивающийся нулевым байтом. Нулевой байт - это байт, каждый бит которого равен нулю, при этом для нулевого байта определена символьная константа ‘\0’ (признак окончания строки или нуль-терминатор). Поэтому, если строка должна состоять из k символов, то в описании массива необходимо указать размер k+1, а при ручном формировании строки в ее окончание нужно явно добавить признак ее окончания.

Операции над строками выполняются только через стандартные функции. Декларации функций для работы со строками размещены в файле string.h. Перечислим некоторые из них, наиболее часто используемые.

1.Функция strcpy(S1, S2) - копирует содержимое строки S2 в строку S1.

2.Функция strcat(S1, S2) - присоединяет строку S2 к строке S1 и помещает ее в массив, где находилась строка S1, при этом строка S2 не изменяется. Нулевой байт, который завершал строку S1, заменяется первым символом строки S2.

3.Функция strcmp(S1, S2) сравнивает строки S1 и S2 и возвращает значение 0, если строки равны, т.е. содержит одно и то же число одинаковых символов; значение <0, если

S1<S2;значение >0, если S1>S2.

4.Функция strlen(S) возвращает длину строки, т.е. количество символов, начиная с нулевого и до нуль-терминатора, нулевой байт не учитывается.

5.Функции преобразования строки S в число:

целое: int atoi(S); длинное целое: long atol(S); действительное: double atof(S); при ошибке возвращает значение 0.

6.Функции преобразования числа V в строку S:

целое: itoa(int V, char S, int kod); длинное целое: ltoa(long V, char S, int kod); 2<=kod<=36,

для отрицательных чисел kod=10.

Помимо традиционной декларации строки, например char sl[51]; можно создавать динамические строки.

Пример создания с использованием библиотечной функции:

45

char *s;

s = (char*)calloc(k,sizeof(char)); // Захват памяти для строки длиной k

Можно воспользоваться и операциями захвата и освобождения динамической памяти. Пример класса с конструктором для создания динамических строковых объектов и

деструктором для их уничтожения после использования в программе. class Stringl {

char *str; public:

Stringl (char *s = "\0") { // Конструктор

str = new char [strlen(s)+l]; strcpy(str,s);

 

}

~String1() {

// Деструктор

 

delete str;

}

void Print(char *sl);

};

void main(void) {

Stringl sl("Minsk"); Stringl s2("Moskow"); s1 .Print("S1");

s2. Print ("S2");

}

Получим: S1 : Minsk

S2 : Moskow

Перегрузка операций в C++ (краткая характеристика)

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

Если компилятор обнаружил, что в программе есть перегрузка операций для объектов конкретного типа, введенных пользователем, то, найдя эти операции, компилятор анализирует их. И, если

операнды имеют встроенный тип данных, то будет заложена стандартная операция;

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

Операции для конкретного класса перегружаются или методом этого класса, или функцией-другом для этого класса следующего вида:

тип operator@(список параметров с указанием их типа) {

код, определяющий смысл указанной операции,

}

@ - символ перегружаемой операции.

Так как операция @ перегружается для объекта конкретного класса, а сам класс - это тип этого объекта, то тип - это идентификатор этого класса.

Отличия перегрузки операций при помощи метода класса или функции-друга следующие:

46

а) @а - унарная операция может быть перегружена методом без параметров и функцией-другом с одним параметром, т.к. у метода имеется первый скрытый от нас параметр (указатель this), который автоматически устанавливается на единственный операнд унарной операции, а функция-друг такого указателя не имеет, потому при перегрузке ее параметров, ее операнд и передают;

б) al @ а2 - бинарная операция перегружается методом класса с одним параметром и функцией-другом с двумя параметрами, т.к. при ее перегрузке методом на первый операнд устанавливается скрытый указатель (this), а второй передаем через параметр; при перегрузке функцией-другом первый операнд передается функцией через первый параметр, второй - через второй параметр.

Рассмотрим пример перегрузки (с использованием функции-друга) операции для класса, порождающего комплексные числа: Класс, порождающий комплексные числа:

zl = re1 +j *im1 = (re1, im1);

т.е. комплексное число - это пара вещественных чисел.

z2 = rel +j * im2 = (re2, im2);

Введем

z3 = (zl + z2) = rе3 +j * im3 = (rе3, im3);

где

rеr = re1 + re2; im3 = iml + im2;

это и составит смысл перегрузки операции «+».

class Complex {

double re, im; public:

Complex(double r, double i) { // Обычный конструктор с параметрами re = r;

im = i;

}

//Декларация функции-друга типа operator friend Complex operator+(Complex, Complex); };

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

Complex operator+(Complex x, Complex y){ Complex z;

z.re = x.re + y.re; z.im = x.im + y.im; return z;

}// Перегрузили

Участок основного кода, иллюстрирующий перегрузку операции «+»:

double a =1.5, b = 2.6, с;

с= а + b;

//Компилятор нашел «+», анализирует данные - это обычные типы, выполняется // стандартная операция

cout « " С = " « endl;

// На экране: С = 4.1

Complex z1(1, 2), z2(3, 4), z3(0, 0);

z3 = zl + z2;

// Выполняется перегруженный «+»

cout «" Z3 : ";

 

47

z3.Print(); getch(); // На экране: Z3 : Re = 4 Im = 6

Упражнение 4. Пользовательский класс String должен содержать необходимые элементы-данные, создаваемые в динамической области памяти.

Конструктор для создания строк:

String (...);

Деструктор:

~String( );

Метод ввода исходной строки

Set( );

Метод печати:

void Print(...);

Код методов - вне пространства определения класса. Программа иллюстрирует прямой и косвенный способы обращения к методам.

Варианты: Ввести строку символов S1, признак окончания ввода строки - нажатие клавиши Enter. Программа должна содержать перегруженную операцию «=», использование которой скопирует S1 в S2 при следующих условиях:

1.Без двух первых и двух последних символов.

2.Без всех чисел, которые делятся на 2.

3.Без всех цифр.

4.Без всех a..z.

5.Без всех A..Z.

6.Без скобок всех видов.

7.Подстроку до первого пробела.

8.Подстроку в фигурных «{ }» скобках.

На печать вывести исходную и преобразованную строки.

Контрольные вопросы

1)Определите назначение меню в программе.

2)Определите процесс создания меню в среде MS Visual C++ 6.0.

3)Назовите случаи, когда возникает событие COMMAND.

4)Как в меню можно создать разделительную линию?

5)По какому правилу IDE MS Visual C++ 6.0 создает ID для пунктов меню.

6)Как создать динамическую строку?

7)В чем заключаются особенности работы со строками в языке Си?

8)Что такое «перегрузка операций»?

9)При помощи чего можно перегрузить операцию в языке Си?

10)Какие отличия в перегрузке унарных и бинарных операциях?

Лабораторная работа №6.

Рисование фигур. Наследование и механизм виртуальных функций

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

Часть 1. Основы программирования в среде Microsoft Visual C++ 6.0. Рисование фигур.

1.Создание нового проекта

Для изучения элементов управления Microsoft Visual C++ 6.0 создадим лабораторную программу, выполняющую следующие действия:

48

Программа Graph рисует круги определенных радиусов в непрерывном режиме. Радиус круга увеличивается, достигает максимума и начинает уменьшаться. Когда радиус круга достигает минимального размера, весь процесс начинается заново.

Когда вы щелкаете по кнопке Draw Graphics на экран выводиться диалоговая панель:

Рис 6.1. Окно лабораторной программы №5

В ней вы можете выбирать цвет круга, с помощью радиокнопок.

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

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

Рис 6.2. Главное окно лабораторной программы №5

Создайте диалоговый проект со следующими параметрами:

Project Name - Graph.

Please enter title of your dialog - The Graph Program.

2.Проектирование диалоговой панели

Расставьте элементы управления как показано на рис. 6.2 и согласно таблице 6.1.

 

 

Таблица 6.1. Оконные элементы программы.

 

 

 

 

Объект

Свойство

Установка

Dialog Box

ID

IDD_GRAPH_DIALOG

 

 

Caption

The Graph Program

 

 

Modal frame

отмечен, страница Extended Styles

 

 

Font

System, Size 10, страница Styles

 

 

Client edge

отмечен, страница Extended Styles

 

 

Static edge

отмечен, страница Extended Styles

 

 

 

49

Push Button

ID

IDC_DRAWGRAPHICS_BUTTON

 

Caption

&Draw Graphics...

 

Modal frame

отмечен, страница Extended Styles

 

Client edge

отмечен, страница Extended Styles

 

Static edge

отмечен, страница Extended Styles

Push Button

ID

IDC_EXIT_BUTTON

 

Caption

E&xit

3.Связывание элементов управления с событиями

Свяжите код с событием BN_CLICKED кнопки Exit

Используйте диалоговую панель ClassWizard для выбора следующего события: Class Name: CGraphDlg

Object ID: IDC_EXIT_BUTTON Messages: BN_CLICKED

Код для функции OnExitButton(): void CGraphDlg::OnExitButton()

{

// TODO: Add your control notification handler code here

////////Мой код начинается здесь///////////

OnOK();

////////Мой код заканчивается здесь///////////

}

4.Установка таймера.

Программа Graph имеет таймер, который является программным механизмом, генерирующем событие WM_TIMER через равные промежутки времени. Код в нашей программе будет задавать частоту, с которой будет выполняться событие WM_TIMER. Если задать рабочий интервал равный 500 миллисекунд, то событие WM_TIMER и связанный с ним код будет выполняться каждые 500 миллисекунд.

Чтобы установить таймер, выполните следующие действия:

1.Выберите ClassWizard в меню View

2.Выберите закладку Message Maps в панели ClassWizard

3.Используйте диалоговую панель ClassWizard для выбора следующего события: Class Name: CGraphDlg

Object ID: СGraphDlg Messages: WM_INITDIALOG

4.Щелкните на кнопку Add Fucntion и в раскрывшемся окне нажмите кнопку OK.

5.Нажмите кнопку Edit Code и напишите следующий код в функции OnInitDialog(): BOOL CGraphDlg::OnInitDialog()

{

CDialog::OnInitDialog();

////////Мой код начинается здесь///////////

///Установить системный таймер int iInstallResult; iInstallResult=SetTimer(1, 50, NULL); if(iInstallResult==FALSE)

{

MessageBox("Cannot install timer", "Error message", MB_OK+MB_ICONERROR);

}

50