- •Л. Б. Бузюков, о. Б. Петрова
- •Учебное пособие
- •Предисловие
- •Глава 1. Введение в язык с
- •1.1. История создания и особенности языка с
- •1.3. Элементы языка с
- •1.3.1. Основные символы
- •1.3.2. Ключевые слова
- •1.3.3. Идентификаторы
- •1.3.4. Константы
- •1.3.5. Лексемы
- •1.3.6. Комментарии
- •Глава 2. Типы данных языка c
- •2.1. Числовые типы данных
- •2.2. Объявление переменных
- •2.3. Данные целого типа
- •2.4. Данные вещественного типа
- •Глава 3. Выражения
- •3.1. Операции
- •3.1.1. Арифметические операции
- •3.1.2. Операция присваивания
- •Глава 4. Составление простейших программ
- •4.1. Препроцессор и его функции
- •4.2. Основные директивы препроцессора
- •4.2.1. Директива include
- •4.2.2. Директива define
- •4.2.3. Директива undef
- •4.3. Структура и правила составления программ
- •4.3.1. Структура функции
- •4.3.2. Функция main()
- •4.3.3. Структура простой программы
- •4.3.4. Правила записи объявлений, операторов и комментариев
- •4.3.5. Пример простейшей программы
- •Глава 5. Средства ввода/вывода
- •5.1. Общие замечания
- •5.2. Функция форматированного вывода printf()
- •5.2.1. Основные форматы
- •5.2.2. Модификации форматов
- •5.3. Функция форматированного ввода scanf()
- •Глава 6. Управляющие операторы
- •6.1. Условные операторы
- •6.1.1. Логические выражения
- •6.1.2. Формы оператора if
- •6.1.3. Оператор выбора switch
- •6.2. Операторы цикла
- •6.2.1. Оператор while
- •6.2.2. Оператор for
- •6.2.3. Оператор do-while
- •6.3. Операторы перехода
- •6.3.1. Оператор break
- •6.3.2. Оператор continue
- •6.3.3. Оператор return
- •6.3.4. Применение оператора goto и меток
- •Глава 7. Функции
- •7.1. Основные понятия
- •7.2. Определение функции
- •7.3. Прототип функции
- •7.4. Вызов функции
- •Глава 8. Классы памяти
- •8.1. Логическаяструктура памяти программы
- •8.2. Особенности классов памяти
- •8.3. Объявления переменных
- •8.4. Объявления функций
- •8.5. Время жизни и область видимости программных объектов
- •8.6. Инициализация глобальных и локальных переменных
- •Глава 9. Указатели
- •9.1. Операция получения адреса
- •9.2. Операции над указателями
- •Глава 10. Массивы
- •10.1. Общие сведения о массивах
- •10.2. Одномерные массивы
- •10.3. Двумерные массивы
- •10.4. Массивы и указатели
- •10.5. Массивы и функции
- •Глава 11. Строки
- •11.1. Представление символьной строки при помощи одномерного массива
- •11.2. Указатель на символьную строку
- •11.3. Ввод/вывод символьных строк
- •11.4. Массивы символьных строк
- •11.5. Функции работы состроками
- •Глава 12. Структуры
- •12.1. Определение структуры
- •12.2. Структуры и функции
- •12.3. Указатели на структуру
- •12.4. Массивы структур
- •12.5. Вложенные структуры
- •12.6. Использование синонима типа
- •12.7. Объединения
- •Глава 13. Файлы
- •13.1. Работа с файлами
- •13.2. Функции ввода/вывода
- •Глава 14. Динамическая память
- •14.1. Распределение памяти
- •14.2. Функции управление памятью
- •Глава 15. Проект
- •15.1. Основы создания проекта
- •15.2. Пример создания проекта
- •Глава 17. Основы объектно-ориентированного программирования
- •17.1. Объектно-ориентированный подход
- •17.3. Конструкторы и деструкторы
- •17.4. Инкапсуляция
- •17.5. Полиморфизм
- •17.6. Наследование
- •17.7. Виды взаимодействия классов
- •17.8. Способы графического представления объектно-ориентированной задачи
- •18.2. Библиотека Win32 api
- •18.3. Библиотека owl
- •18.4. Библиотека vcl
- •18.5. Библиотека clx
- •18.6. Библиотека mfc
- •18.7. Библиотека OpenGl
- •19.3. Создание проекта
- •19.4. Редактирование проекта
- •19.5. Компиляция и выполнение программы
- •19.6. Файловая структура проекта
- •19.7. Создание консольного приложения
- •Глава 20. Разработка приложений для операционных систем windows
- •20.1. Взаимодействие программы и Windows
- •20.2. Компоненты библиотеки Win32 api
- •20.3.Функция WinMain()
- •20.4. Оконная процедура
- •20.5. Структура программы для ос Windows
- •20.6. Ресурсы Windows
- •20.7. Взаимодействие прикладной программы и устройств в Windows
- •Глава 21. Создание приложений для ос windows на основе библиотеки mfc
- •21.1. Обзор классов библиотеки mfc
- •21.2. Класс cString
- •21.3. Класс cFile
- •21.4. Класс cPoint
- •21.5. Класс cRect
- •21.7. Приложение, основанное на диалоге
- •21.8. Использование в приложении элементов управления
- •21.9. Мастер классов mfc ClassWizard
- •21.10. Установка начального значения элементам управления
- •21.11. Элементы управления Picture
- •21.12. Элемент управления Group Box
- •21.13. Элемент управления Radio Button
- •21.14. Элемент управления Check Box
- •21.15. Элемент управления List Box
- •21.16. Создание меню
- •21.17. Приложение с двумя диалоговыми панелями
- •21.18. Приложение sdi
- •21.19. Создание панели инструментов
- •21.20. Приложение mdi
- •21.21. Контекстыустройств в mfc
- •21.22. Графические объекты Windows в mfc
- •21.23. Графические операции в mfc
- •П.1. Основы методологии конструирования программ
- •П.1.1. Основные понятия. Программа и алгоритм
- •П.1.2. Этапы разработки программ
- •П.2. Алгоритмы
- •П.2.1. Алгоритм и его свойства
- •П.2.2. Способы описания алгоритмов
- •П.2.3. Средства графического изображения алгоритмов Схемы алгоритмов
- •Псевдокоды
- •Структурограммы
- •П.3. Основные приемы программирования
- •П.3.1. Разновидности структур программирования
- •П.3.2. Программирование линейных и разветвляющихся процессов
- •П.3.3. Программирование циклических процессов
- •Арифметический цикл (цикл с параметром)
- •Итерационный цикл
- •Вложенный цикл
- •Литература
17.5. Полиморфизм
Полиморфизм – это принцип ООП, позволяющий включать в состав класса несколько функций с одинаковыми именами, но выполняющих различные действия. Такие функции должны иметь различные списки параметров, они должны отличаться или количеством параметров в списках, или типами соответствующих параметров. Полиморфизм в ООП есть проявление свойства языка C++, называемого перегрузкой функций (п. 16.4).
Пример полиморфизма – класс графических примитивов Draw. Класс может проявить себя как текст, прямоугольник или окружность. Для этого в класс включены три метода show(), различающиеся параметрами.
Компилятор, обрабатывая вызов функции, сопоставляет список фактических параметров со списками формальных параметров всех методов класса, имеющих то же имя, и выбирает ту функцию, у которой список формальных параметров совпал со списком фактических параметров при вызове функции:
#include <string.h>
#include <iostream.h>
class Draw
{
int x1, y1, x2, y2, r;
char *message;
public:
Draw();
virtual ~Draw();
void show();
void show(int xx1, int yy1, int xx2, int yy2);
void show(int xx1, int xx2, int rr);
};
Draw::Draw()
{
x1=x2=y2=y1=r=0;
message=new char[10];
strcpy(message, "text");
}
Draw::~Draw()
{
delete[] message;
message=NULL;
}
void Draw::show()
{
cout << message << endl;
}
void Draw::show(int xx1,int yy1,int xx2,int yy2)
{
cout << "Rectangle" << endl;
}
void Draw::show(int xx1,int xx2,int rr)
{
cout << "Circle" << endl;
}
int main(void)
{
Draw draw;
draw.show();
draw.show(1,1,20,10);
draw.show(10,10,10);
return 0;
}
В результате выполнения программы на экране появляются сообщения:
Text
Rectangle
Circle
17.6. Наследование
Наследование – это принцип ООП, посредством которого на базе существующих классов создаются новые классы, получающие по наследству от базовых классов свойства и методы. Наследование позволяет существенно экономить программный код.
Созданные с использованием механизма наследования новые классы называются классами-наследниками или классами-потомками.
//Объявление базового класса
class A
{
… //Члены класса A
};
//Объявление класса-наследника
class B : public A
{
… //Собственные члены класса B
};
Новые классы наследуют только те свойства и методы, которые объявлены в разделах public и protected базовых классов. При этом свойства и методы из раздела protected доступны только базовому классу и его наследникам, тогда как свойства и методы из раздела public доступны объектам любого класса (рис. 17.1). Исключением из этого правила являются конструкторы и деструкторы, которые не наследуются.
Рис. 17.1. Уровни доступа к членам класса
В состав класса B входят собственные члены и члены класса A из разделов public и protected.
Рассмотрим пример наследования, в качестве базового класса возьмем класс person, характеризующий любого человека, и включим в раздел protected свойство класса name – имя человека:
class person
{
protected:
char name[20];
};
Создадим на основе класса person класс-наследник student:
class student : public person
{
char department[20]; // факультет
public:
student(char* _name, char* _department);
void message();
};
//Конструктор
student :: student(char* _name, char* _department)
{
strcpy(name, _name);
strcpy(department, _department);
}
//message – метод, сообщающий сведения об объекте
void student::message()
{
cout << "My name is " << name << ". I study at " << department << endl;
}
Как видно, методы класса student используют как собственное свойство, так и свойство, полученное по наследству.
Создание объекта класса student и вызов его метода ничем не отличаются от того, как это делается для класса без наследования:
int main(void)
{
student N("Nick", "SS,SK,VT");
N.message();
return 0;
}
Во время выполнения такой программы на экране появляется сообщение:
My name is Nick. I study at SS, SK, VT.
Теперь рассмотрим наследование методов базового класса, включим в базовый класс конструктор, инициализирующий собственное свойство базового класса значением "Noname", и метод message, сообщающий информацию о классе:
class person
{
protected:
char name[20];
public:
person();
void message();
};
person :: person()
{
strcpy(name, "Noname");
}
void person::message()
{
cout << "My name is " << name << endl;
}
Таким образом, в класс-наследник student теперь включены два метода message, имеющие одинаковый тип и одинаковый список параметров – один из базового класса, другой – собственный. Собственный метод доступен через имя объекта. Однако можно получить доступ к унаследованному методу, если использовать для доступа к методу указатель соответствующего типа – указатель на базовый класс:
int main(void)
{
person A;
student B("Ann", "SS,SK,VT");
A.message();
B.message();
person* pperson = &B;
pperson->message();
student* pstudent = &B;
pstudent->message();
return 0;
}
На экране увидим сообщения:
Noname Сообщение об= объекте A
Ann SS,SK,VT Сообщение об объекте B (используется
собственный метод message)
Ann Сообщение об объекте B (используется
метод message, полученный по наследству)
Ann SS,SK,VT Сообщение об объекте B (используется
собственный метод message)
В С++ можно избежать получения по наследству метода, если метод с таким же именем включен в класс-потомок, для этого используется механизм виртуальных функций.
Виртуальная функция - это функция, объявленная в базовом классе с помощью ключевого слова virtual, такая функция в классах-потомках замещается на функцию, принадлежащую производному классу и имеющую то же имя:
class person
{
protected:
char name[20];
public:
person();
virtual void message();
};
Теперь результатом выполнения программы будут следующие сообщения:
Noname Сообщение об объекте A
Ann SS,SK,VT Сообщение об объекте B (используется
собственный метод message)
Ann SS,SK,VT Сообщение об объекте B (используется
собственный метод message)
Ann SS,SK,VT Сообщение об объекте B (используется
собственный метод message)
С помощью виртуальных функций можно создать класс-наследник, имеющий тот же интерфейс, что и базовый класс, но обладающий своей собственной моделью поведения. Механизм виртуальных функций реализуется следующим образом: обычно обработка вызовов функций выполняется на этапе компиляции и завершается на этапе редактирования связей, когда вызов метода жестко связывается с соответствующей функцией (раннее связывание); если метод объявлен как виртуальный, выполняется так называемое позднее связывание, т. е. связывание вызова и функции во время выполнения программы.
