Здравствуйте!
Программирование 5, 6 модули
Рекомендуемая литература
Жизненная философия
Жизненная философия
Как быть хорошим программистом
Как быть хорошим программистом
Как быть хорошим программистом
Что нам предстоит
Система оценок
Система оценок
Система оценок
Система оценок
Система оценок
Система оценок
Курсовая работа (л/р №4)
Курсовая работа
Курсовая работа
Иерархия языков
Понятие объекта и класса
Понятие объекта и класса
Понятие объекта и класса
Понятие объекта и класса
Понятие объекта и класса
Понятие объекта и класса
Понятие объекта и класса
Понятие объекта и класса
Понятие объекта и класса
Абстракция
Классом может быть и абстрактная сущность
Классом может быть и абстрактная сущность
Классом может быть и абстрактная сущность
Классом может быть и абстрактная сущность
Достоинства: модульность
Достоинства: простота
Инкапсуляция
Инкапсуляция
Синтаксис
Синтаксис
Синтаксис
Синтаксис
Синтаксис
Синтаксис
Синтаксис
Область видимости
Область видимости
Область видимости
Область видимости
Пример
Пример
Пример
Пример
Пример использования
Первый принцип программиста
Второй принцип программиста
Третий принцип программиста
Четвертый принцип программиста
Как быть?
Как быть?
Конструктор
Деструктор
Пример
Пример
Пример
Пример
Пример
Пример
Выделение памяти
Выделение памяти
Выделение памяти
Выделение памяти
Освобождение памяти
Освобождение памяти
Конструктор вызывается
Деструктор вызывается
Для временных переменных
Пример
Пример
Чему учит нас Летающий Макаронный Монстр?
Значит передавать по ссылке?
Да, но только по константной
Да, но только по константной
Область видимости переменной
Область видимости переменной
Область видимости переменной
Указатель на функцию
Указатель на функцию
Зачем это надо?
Зачем это надо?
Зачем это надо?
Удобнее так
Удобнее так
Удобнее так
Для классов
Для классов
Для классов
Давайте немного попишем
Сигналы и слоты в Qt
Вы не видите ничего странного?
Вы не видите ничего странного?
Сигналы и слоты в Qt
Сигналы и слоты в Qt
Сигналы и слоты в Qt
Сигналы и слоты в Qt
Сигналы и слоты в Qt
Дэн, ай нид хэлп
Вы не видите ничего странного?
Вы не видите ничего странного?
А это что?
А это что?
Но есть нюанс
Model-View-Controller
Спроектируем игру
«Юный логистик»
«Юный логистик»
«Юный логистик 2.0»
«Юный логистик 2.1 (несколько игроков)»
«Юный логистик 2.2 (сеть)»
«Юный логистик 2.3 (сеть+ИИ)»
Результаты контрольной
Самые интересные ошибки
Самые интересные ошибки
Что хотелось увидеть
Что хотелось увидеть
Что хотелось увидеть
Результаты контрольной
Самые интересные ошибки
Что хотелось увидеть
Да, у них было проще
Некоторые классы умеют так
Но, черт возьми, как?
Ответ
А как именно?
А как именно?
Но есть нюанс
Но есть нюанс
Но есть нюанс
Но есть нюанс
Но есть нюанс
Но есть нюанс
В итоге a += b + c - d; станет
Семантика переноса
В итоге a += b + c - d; станет
Операторы вне класса
Операторы вне класса
Друзья класса
Друзья класса
Параметры по умолчанию
Параметры по умолчанию
Параметры по умолчанию
Параметры по умолчанию
Параметры по умолчанию
Параметры по умолчанию
Внимание, конкурс!
LMS работает странно
Давайте немного попишем
Нет, не контрольная
Результаты опроса
Результаты опроса
Результаты опроса
Результаты опроса
Результаты опроса
Результаты опроса
Продолжим наши игры
Продолжим наши игры
Как это делать?
Зачем это нужно?
Зачем это нужно (1)?
Зачем это нужно (1)?
Зачем это нужно (1)?
Интерфейс (2)
Интерфейс (2)
Интерфейс (2)
Типичные ошибки
Типичные ошибки
Типичные ошибки
Инициализация объектов
Инициализация объектов
Инициализация объектов
Инициализация объектов
Инициализация объектов
Инициализация объектов
Зоны видимости
Зоны видимости
Зоны видимости
Перегрузка функций
Перегрузка функций
Виртуальные функции
Виртуальные функции
Ах, как было бы здорово, …
Есть такая партия!
Виртуальные функции
Виртуальные функции
Виртуальные функции
Виртуальные функции
Абстрактные функции
Более правильное решение
Более правильное решение
Новые возможности
Пример
Пример 2
Пространство имен
Пространство имен
Пространство имен
Пространство имен
Библиотека ввода/вывода
Консольный ввод/вывод
Класс istream
Класс istream
Класс ostream
Класс istream
Класс istream
Класс istream
Класс ifstream
explicit
explicit
Класс ifstream
Класс ifstream
Класс ifstream/ofstream
Класс ifstream
Класс ifstream (пример)
Класс ifstream (пример)
Класс ifstream (пример)
Сериализация объектов
Сериализация объектов
Сериализация объектов
Сериализация объектов
Класс ifstream
Класс ifstream
Класс ifstream
Класс ifstream
Класс ifstream
Класс ifstream
Что нас ждет в конце модуля?
Разбор полетов, мысли
Разбор полетов, мысли
Перспективы
Перспективы
Перспективы
Разбор полетов, мысли
Что делать, если нужна глобальная переменная?
Пример
Объявление статических переменных
Объявление статических переменных
Чему нас учит к.м.н. Хаус?
Объявление статической переменной
Кстати об инициализации
Статические методы
Пример
Пример 2
Пример 3 QString Static Public Members
Отслеживание ошибок
Например
Например 2
Исключительные ситуации
Исключительные ситуации
Например
Исключительные ситуации
Порождение исключений
Например 2
Например 3
Например 4
Например 4
Исключительные ситуации
Исключительные ситуации STL
Например
Например
Исключительные ситуации
Проблема
Пусть будет «Нет» и я хитр
Шаблонные функции
«Нет» и я образован
«Нет» и я современно образован
«Нет» и я образован, хитер и невнимателен
Вызов шаблонной функции
Вызов шаблонной функции
Параметры шаблонов
Типичные ошибки
Типичные ошибки
Типичные ошибки
Несколько типов шаблонов
Шаблонные классы
Функции шаблонных классов
Переменные шаблонных классов
Несколько типов шаблонов
Шаблонные классы
Наследование от шаблонов
Особенности работы с шаблонами
Учет переменных по-новому
Учет переменных по-новому
Учет переменных по-новому
Определения типов внутри шаблонного класса
Параметр-шаблон
Сложный пример
Сложный пример
Типы как члены класса
Типы как члены класса
Почему это вызывает ошибку?
Типы как члены класса (развитие идеи)
А теперь выучим новое слово
Например
Например
Проблема
Откуда взялась проблема
Как мы думали оно работает
Как мы думали оно работает
Как мы думали оно работает
Как мы думали оно работает
Как мы думали оно работает
Как мы думали оно работает
Откуда взялась проблема
Откуда взялась проблема
Откуда взялась проблема
Откуда взялась проблема
Откуда взялась проблема
Откуда взялась проблема
Решение
Решение (на самом деле)
Решение
Решение
Решение
Решение
Решение
Решение
Что для этого есть в Qt?
Почему это плохо?
Класс QThread
Класс QThread
Как сделать лучше
Как сделать еще лучше
Как сделать еще лучше
Как сделать еще лучше
Возможные проблемы
Мьютексы
QMutex
Например
QMutex
Например
Например
Например
Например
Например
Например
Например
Например
Например
QSemaphore
QSemaphore
QSemaphore
Например
Например
Например
Например
Например
Например
Например
Например
Например
3.41M
Категория: ПрограммированиеПрограммирование

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

Здравствуйте! Меня зовут Клышинский Эдуард Станиславович [email protected] Программирование 5, 6 модули (Объектно-ориентированное программирование) МИЭМ НИУ ВШЭ, Клышинский Э.С.

2013 г.

Рекомендуемая литература

• М.

Шлее Qt 4.8.

Профессиональное программирование на C++ (655 руб.)

• Б.

Страуструп Программирование.

Принципы и практика использования C++ (2560 руб.)

• С.

Прата Язык программирования C+ + (C++11).

Лекции и упражнения (1909 руб.)

• http://www.cplusplus.com/

• http://habrahabr.ru/ Введение Как мы будем жить Жизненная философия

• Шу (семинары и лабораторные) – ученик не способен задать правильные вопросы и понять ответы

• Ха (лекции) – ученик постоянно совершенствует свою технику и спрашивает «Почему?»

• Ри (курсовая) – ученик постоянно экспериментирует, смешивает техники, пробует разработать собственный стиль.

Жизненная философия У нас нет времени делать это последовательно! Как быть хорошим программистом The first requirement for programming is a passion for the work, a deep need to probe the mysterious space between human thoughts and what a machine can understand;

between human desires and how machines might satisfy them.

“How to be a Woman Programmer,” Ellen Ullman Как быть хорошим программистом The second requirement is a high tolerance for failure.

Programming is the art of algorithm design and the craft of debugging errant code.

“How to be a Woman Programmer,” Ellen Ullman Как быть хорошим программистом You need the willingness to fail all the time.

You have to generate many ideas and then you have to work very hard only to discover that they don’t work.

And you keep doing that over and over until you find one that does work.

John Backus, inventor of the Fortran programming language Что нам предстоит

• Лекции

• Семинары

• Лабораторные работы (5 модуль): 1.Разработка контейнера.

2.Визуальный интерфейс для разработанного контейнера, сохранение.

3.Контейнер для базового класса.

4.Разработка большого приложения.

Система оценок Лабораторные работы (5 модуль): 1 – 1 балл, 2 – 1 балл, 3 – 2 балла, 4 – 2 балла.

Зачет – 4 балла.

Старосты! Нам нужны актуальные списки! Система оценок Указанные баллы являются максимумом, который можно получить за работу.

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

Система оценок К хорошим программистом приходит Дед Мороз.

К плохим – DeadLine.

Система оценок По лабораторным работам назначается срок сдачи.

Если работа сдается на неделю позже по вине студента, максимальный балл уменьшается на 25%, если на две – на 50%, если позже – оценка не ставится.

Система оценок Лабораторные работы, выполненные в противоречии правилам хорошего тона НЕ ПРИНИМАЮТСЯ!!! Система оценок Если сумма баллов за ниже 4 баллов, берется целая часть от полученной суммы.

Если сумма баллов выше 4, то проводится арифметическое округление.

Курсовая работа (л/р №4) Команда из n∈ [1;2] человек должны написать n*[400;600] строк кода по выбранной теме.

Требования на «отлично»:

• классы

• наследование

• перегрузка операторов

• шаблоны

• полиморфизм Курсовая работа Команда из n∈ [1;2] человек должны написать n*[400;600] строк кода по выбранной теме.

Требования на «хорошо»:

• классы

• наследование Курсовая работа Команда из n∈ [1;2] человек должны написать n*[400;600] строк кода по выбранной теме.

Требования на «удовлетворительно»:

• классы Лекция 1,2 Основные понятия Иерархия языков Процедурное программирование Ассемблер Структурное программирование Объектно- ориентированное программирование Что понимает компьютер.

Как человеку проще записывать действия.

Как человеку проще описывать данные.

Как человеку проще мыслить.

Понятие объекта и класса Весь мир состоит из объектов, поэтому человеку проще манипулировать именно объектами, а не наборами переменных.

Понятие объекта и класса Что объединяет эти вещи? Понятие объекта и класса Стул — мебельное изделие для сидения одного человека, со спинкой, с подлокотниками или без них, с высотой сиденья, функционально удобной при соотношении его с высотой стола.

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

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

Также промежуток между спинкой и сиденьем может быть заполнен декоративным элементом.

Википедия Понятие объекта и класса Стул — мебельное изделие для сидения одного человека, со спинкой, с подлокотниками или без них, с высотой сиденья, функционально удобной при соотношении его с высотой стола.

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

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

Также промежуток между спинкой и сиденьем может быть заполнен декоративным элементом.

Википедия Это свойства объекта Понятие объекта и класса Стул — мебельное изделие для сидения одного человека, со спинкой, с подлокотниками или без них, с высотой сиденья, функционально удобной при соотношении его с высотой стола.

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

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

Также промежуток между спинкой и сиденьем может быть заполнен декоративным элементом.

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

В отличие от идеи эйдос уже не генерализует, но наоборот выделяет и отличает вещь от других вещей.

Понятие объекта и класса Класс – некоторый шаблон, описывающий создаваемые объекты (эйдос, идея).

Объекты – фрагменты оперативной памяти, расположение элементов которых описывается заданным классом (элементы окружающего мира).

Понятие объекта и класса Класс (шаблон) class Ui_MainWindow{ public: QWidget *centralWidget;

QLineEdit *Pix_path;

QPushButton *pushButton_3;

QPushButton *pushButton_2;

QLineEdit *lineEdit;

QPushButton *pushButton_9;

QPushButton *pushButton;

QProgressBar *progressBar;

void setupUi(QMainWindow *MainWnd);

void retranslateUi(QMainWindow *MainWnd);};

0x0d45f124 0x0d45f136 0x0d45f048 0x0d45f256 0x0d45e512 0x0d45e112 0x0d45e648 0x0d453248… mov ax, dx imul ax, 6… push ax push cx… объекты (данные) методы Абстракция Буч Г.

Объектно-ориентированный анализ и проектирование Классом может быть и абстрактная сущность - ...начинается на _M_, - продолжала она.

- Они рисовали мышеловки, месяц, математику, множество...

Ты когда-нибудь видела, как рисуют множество? - Множество чего? - спросила Алиса.

- Ничего, - отвечала Соня.

- Просто множество! - Не знаю, - начала Алиса, - может...

- А не знаешь - молчи, - оборвал ее Болванщик.

Классом может быть и абстрактная сущность - ...начинается на _M_, - продолжала она.

- Они рисовали мышеловки, месяц, математику, множество...

Ты когда-нибудь видела, как рисуют множество? - Множество чего? - спросила Алиса.

- Ничего, - отвечала Соня.

- Просто множество! - Не знаю, - начала Алиса, - может...

- А не знаешь - молчи, - оборвал ее Болванщик.

Кстати, это не наши методы.

Лучше задавайте вопросы.

Классом может быть и абстрактная сущность Множество Свойства : массив элементов, количество элементов в массиве Методы : добавить элемент, удалить элемент, очистить, выбрать элемент, найти элемент Классом может быть и абстрактная сущность Заслуга Свойства : дата, место, наименование Методы : отобразить, установить дату (в целях проверки корректности входных данных), вернуть дату Достоинства: модульность Буч Г.

Объектно-ориентированный анализ и проектирование Достоинства: простота Буч Г.

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

Важно понимать, что к инкапсулированной переменной можно обратиться при написании реализации класса, но при его использовании обращение к ней невозможно.

Инкапсуляция Следует различать интерфейс класса, то есть то, что он предоставляет для использования другим фрагментам кода, от реализации класса, то есть описания собственно механизма функционирования.

Синтаксис class TheClassName // class имя_класса{ public: // Магической слово int property1;

// свойства класса double property2, property3;

int methodFoo(int a, char *b);

// методы float methodBar();};

Синтаксис class TheClassName // порядок не важен{ public: // Магической слово double property2, property3;

int methodFoo(int a, char *b);

// методы int property1;

// свойства класса float methodBar();};

Синтаксис class TheClassName // порядок не важен {public:double property2,property3;int methodFoo(int a,char*b);int property1;float methodBar();};

// Да, как и форматирование кода Синтаксис int TheClassName::methodFoo(int a, char *b){ property3=a;

property1=strlen(b);

return 0;} float TheClassName::methodBar(){ property2=0;

return 0.;} Синтаксис #include “myclass.h” int main() {TheClassName obj1, *obj2=&obj1;

obj1.property1=0;

obj1.methodBar();

obj2->methodFoo(10, “строка”);} Синтаксис class TheClassName2 //{ public: TheClassName *objects;

int count;

void add(TheClassName &obj);

void delete(int pos);};

Синтаксис class TheClassName2 //{ public: TheClassName *objects;

int count;

void add(TheClassName& obj);

void delete(int pos);};

Ссылка на параметр, параметр может изменяться внутри функции.

Область видимости public – то, что написано в этой строке будет доступно «снаружи» класса.

public: – то, что написано ниже будет доступно «снаружи» класса.

private – то, что написано в этой строке будет доступно только методам класса.

private: – то, что написано ниже будет доступно только методам класса.

Область видимости По умолчанию свойства и методы класса являются private, поэтому забыв написать public мы лишаем класс интерфейса.

Структура – тоже класс и она может иметь методы.

В целях совместимости все ее члены и методы по умолчанию public.

Область видимости Общее правило.

По умолчанию всё, что не обязано быть доступно снаружи, обязано быть private.

Пожалейте других разработчиков! Область видимости Общее правило.

Правила хорошего тона предписывают описать сперва открытые члены класса, а потом закрытые.

Пожалейте других разработчиков! Пример Мы пишем экономическую стратегию (игра).

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

Время дискретно, внешний класс (игра) сообщает о его течении.

Пример Свойства: название ресурса, количество ресурса, производительность, интервал производства, количество произведенных ресурсов, число работников, максимальное число работников.

Методы: прошло время Пример class Mine // Часть свойств опущено{ public: char *resName;

// Имя ресурса // Сколько есть ресурса, сколько произведено int overall, produced;

// Число работников, мах число работников int workerCount, maxWorkerCount;

// Тикает время bool tick();};

Пример bool Mine::tick() {double tmp;

curTime++;

if( curTime>=interval ) {curTime = 0;

tmp = ((double) workerCount) / maxWorkerCount;

produced += productivity * tmp;

return true;

} return false;} Пример использования int main() {Mine mn;

mn.maxWorkerCount=0;

mn.productivity=-1 mn.resName=(0xFACE8D00);

mn.tick();} И кого будут ругать? Первый принцип программиста КРУГОМ ВРАГИ! Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете.

(с) Стив Макконнелл Второй принцип программиста Надо инициализировать переменные Буратино дали пять яблок, сколько яблок у него стало? Неизвестно, так как неизвестно, сколько яблок у него было до того.

Третий принцип программиста Работа выполнена, если за нее заплачены деньги.

(Раз уж мы об этом заговорили.) Четвертый принцип программиста КОПИРОВАНИЕ – ЗЛО! (Раз уж мы об этом заговорили.) Как быть? Принцип 1 вступает в противоречие с принципом 2.

Мы не можем спрятать переменные, так как их надо инициализировать.

И мы не можем оставить их доступными, так как возможны ошибки.

Как быть? Надо завести функцию инициализации и спрятать все данные! Но наши коллеги забудут ее вызвать.

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

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

Пример class Mine {public: Mine();

// Конструктор по умолчанию Mine(char *name, int amount, int prdctvt, int intrvl);

// Инициализирующий конструктор Mine(Mine &mn);

// Копирующий конструктор Mine(Mine &&mn);

// Конструктор переноса ~Mine();

// Деструктор bool tick();

bool addWorker();

bool getWorker();

Пример private: char *resName;

// Имя ресурса // Сколько есть ресурса, сколько произведено int overall, produced;

// Число работников, мах число работников int workerCount, maxWorkerCount;};

Пример Mine::Mine() {resName=NULL;

overall=0;

produced=0;

workerCount=0;

maxWorkerCount=0;

// И так далее} Пример Mine::Mine(char *name, int amount, int prdctvt, int intrvl) {resName=new char [strlen(name)];

overall=amount;

produced=0;

workerCount=0;

maxWorkerCount=0;

// И так далее} Пример bool Mine::addWorker() {if( workerCount == maxWorkerCount ) return false;

workerCount++;

return true;} bool Mine::getWorker() {if( workerCount == 0 ) return false;

workerCount--;

return true;} Пример int main() {Mine mine1;

Mine mine2(“Mine2”, 100, 1, 50);

Mine mine3(mine2);

// Дальше идет код} Выделение памяти Функция malloc ничего не должна знать про конструктор и деструктор, она только выделяет память.

Поэтому используется оператор new.

Выделение переменной указатель = new тип;

Выделение массива Указатель = new тип [кол-во элементов];

Выделение памяти Mine *newMine, *mine2, *mine3;

newMine=new Mine;

newMine->addWorker();

Выделение памяти Для вызова инициализирующих конструкторов можно использовать конструкцию указатель = new тип ( параметры );

Mine *newMine, *mine2, *mine3;

newMine=new Mine;

newMine->addWorker();

mine2=new Mine(newMine);

mine3=new Mine(“Mine3”, 900, 2, 30);

Выделение памяти int **arr;

int cnt, i, j;

scanf(“%d”, cnt);

arr=new int * [cnt];

for( i=0;

i<cnt;

i++ ) {arr[i]=new int[cnt];

for( j=0;

j<cnt;

j++ ) arr[i][j]=i+j;} Освобождение памяти Функция free ничего не знает про деструктор, поэтому надо пользоваться delete.

Удаление переменной delete указатель;

Удаление массива delete [] указатель;

Освобождение памяти Внимание! Всё, что выделялось с квадратными скобками с ними же и удаляется! delete null;

или delete [] null;

Это работает! Конструктор вызывается … при любом создании объекта:

• создании переменной (локальной или глобальной – не важно);

• динамическом выделении памяти (использование new);

• передаче параметра-объекта в функцию;

• создании временного объекта для вычисления результата;•… Деструктор вызывается … при любом уничтожении объекта:

• закончилось время жизни (зона видимости) переменной (локальной или глобальной – не важно);

• освобождении динамически выделенной памяти (использование delete);

• передаче параметра-объекта в функцию (после возвращения из функции);

• удалении временного объекта для вычисления результата (после вычислений);•… Для временных переменных … для снятия копии вызывается копирующий конструктор.

Если его нет, снимается побайтовая копия с копируемого объекта.

Пример class Stack {public: Stack();

~Stack();

void push(int);

int pop();

private: int *data;

int count;};

void func(Stack st){ // Много кода} void func2() {Stack s;

// Код func(s);

// Еще код} Пример void func2() {Stack s;

data0xAD067820 count10 1234567890 func(s);

void func(Stack s){ data0xAD067820 count10 } // почти delete &s;

Чему учит нас Летающий Макаронный Монстр? 9.

Лучше бы ты не передавал объекты по значению, равно как и массивы.

Это не способствует проявлениям любви к тебе со стороны ближних.

Значит передавать по ссылке? -- Кристофер Робин, ты должен сбить шар из ружья.

Ружье у тебя с собой? -- Понятно, с собой,-- сказал Кристофер Робин.-- Но если я выстрелю в шарик, он же испортится! -- А если ты не выстрелишь, тогда испорчусь я,-- сказал Пух.

Да, но только по константной void func(const Stack &st){ // Так можно int n=st.getCount();

if( st.getCount==0 ) { // Так нельзя st.push(444);

}} class Stack {public: Stack();

~Stack();

void push(int);

int pop();

int getCount() const;

private: int *data;

int count;};

Да, но только по константной int Stack::getCount() const{ count++;

// нельзя return count;

// можно} class Stack {public: Stack();

~Stack();

void push(int);

int pop();

int getCount() const;

private: int *data;

int count;};

Переменная видна с момента ее объявления до соответствующей закрывающей скобки Область видимости переменной int Stack::push(int d) {int i, t;

int *tmp;

tmp=new int[count+1];

for( i=0;

i<count;

i++ ) {t=data[i] tmp[i]=t;

} tmp[count++]=d;

delete [] data;

data=tmp;

} Переменная видна с момента ее объявления до соответствующей закрывающей скобки Область видимости переменной int Stack::push(int d) {int i;

int *tmp;

tmp=new int[count+1];

for( i=0;

i<count;

i++ ) {int t=data[i] tmp[i]=t;

} tmp[count++]=d;

delete [] data;

data=tmp;} Переменная видна с момента ее объявления до соответствующей закрывающей скобки Область видимости переменной int Stack::push(int d){ int *tmp;

tmp=new int[count+1];

for( int i=0;

i<count;

i++ ) {int t=data[i] tmp[i]=t;

} tmp[count++]=d;

delete [] data;

data=tmp;} Переменная видна с момента ее объявления до соответствующей закрывающей скобки Область видимости переменной int somefunc(int **data, int cnt) {int i, sum;

for( sum=0, i=0;

i<cnt;

i++ ) for( int i=0;

i<cnt;

i++ ) sum+=data[::i][i];

return sum;} Область видимости переменной int somefunc(int **data, int cnt) {int i, sum;

for( sum=0, i=0;

i<cnt;

i++ ) for( int i=0;

i<cnt;

i++ ) sum+=data[::i][i];

return sum;} i из цикла i верхнего уровня Лекция 3 Разработка визуальных интерфейсов в Qt Указатель на функцию int (*pt2Function)(float, char, char);

pt2Function представляет собой переменную, указывающую на начало функции, которая возвращает int и принимает float, char и char.

Указатель на функцию int f1(float a, char b, char c) { // place your code here } int f2(float a, char b, char c) { // place your code here } int main() {int (*pt2Function)(float, char, char);

pt2Function=f1;

pt2Function(1.1, ‘d’, ‘f’);} Зачем это надо? int cmpMines1(const Mine &m1, const Mine &m2) {if(m1.getProduct()==m2.getProduct()) return 0;

// …} int cmpMines2(const Mine &m1, const Mine &m2) {if(m1.getInterval()>m2.getInterval()) return 1;

// …} Зачем это надо? void sortMines(Mine *mines, int count, int (*cmpFunc) (const Mine &m1, const Mine &m2) ){ for( int i=0;

i<count;

i++ ) for( int j=i+1;

j<count;

j++ ) if(cmpFunc(mines[i],mines[j])<0) swapMines(mines[i], mines[j]);} Зачем это надо? int main() { Mines mns[100];

int mCount;

// Some initializations here if( sortByProd ) sortMines( mns, mCount, cmpMines1);

else if( sortByInterval ) sortMines( mns, mCount, cmpMines2);

// and so on} Удобнее так typedef int (*cmpFuncType) (const Mine &m1, const Mine &m2) );

Теперь cmpFuncType – это тип указателя на функцию сравнения двух шахт.

Удобнее так enum SortModes={smProd, smInterval, smWorkers};

class MinesCollection {// Some code here public: void setSortingMode(SortModes mode);

void sortMines();

// code private cmpFuncType ptr;} Удобнее так enum SortModes={smProd, smIntr, smWrk};

void MinesCollection::setSortingMode(SortMod es mode) { switch( mode ) {case smProd: ptr=cmpMines1;

return;

case smIntr: ptr=&cmpMines2;

return;

// А еще добавить по возрастанию или убыванию.

}} Для классов // Взято с http://www.newty.de/fpt/fpt.html class TMyClass { public: int DoIt(float a, char b, char c);

int DoMore(float a, char b, char c) const;

// more code};

Для классов int (TMyClass::*pt2Member)(float, char, char) = null;

int (TMyClass::*pt2ConstMember)(float, char, char) const = null;

pt2ConstMember = &TMyClass::DoMore;

pt2Member = &TMyClass::DoIt;

// pt2Member может показывать и на &DoMore Для классов TMyClass instance1;

int result3 = (instance1.*pt2Member) (12, 'a', 'b');

int result4 = (*this.*pt2Member)(12, 'a', 'b');

TMyClass* instance2 = new TMyClass;

int result4 = (instance2->*pt2Member) (12, 'a', 'b');

delete instance2;

Давайте немного попишем Сигналы и слоты в Qt Вы не видите ничего странного? #include <QObject> class Counter : public QObject { Q_OBJECT public: Counter() { m_value = 0;

} int value() const { return m_value;

} public slots: void setValue(int value);

signals: void valueChanged(int newValue);

private: int m_value;};

Вы не видите ничего странного? #include <QObject> class Counter : public QObject { Q_OBJECT public: Counter() { m_value = 0;

} int value() const { return m_value;

} public slots: void setValue(int value);

signals: void valueChanged(int newValue);

private: int m_value;};

Сигналы и слоты в Qt void Counter::setValue(int value){ if (value != m_value) { m_value = value;

emit valueChanged(value);

}} Сигналы и слоты в Qt Counter a, b;

QObject::connect(&a, &Counter::valueChanged, &b, &Counter::setValue);

a.setValue(12);

// a.value() == 12, b.value() == 12 b.setValue(48);

// a.value() == 12, b.value() == 48 Сигналы и слоты в Qt Counter a, b, c, d;

QObject::connect(&a, &Counter::valueChanged, &b, &Counter::setValue);

QObject::connect(&a, &Counter::valueChanged, &c, &Counter::setValue);

QObject::connect(&b, &Counter::valueChanged, &d, &Counter::setValue);

a.setValue(12);

// a==12, b==12, c==12, d==12 b.setValue(48);

// a==12, b==48, c==12, d==48 Сигналы и слоты в Qt “+” На один сигнал можно «повесить» много слотов.

Инициируя сигнал мы можем не беспокоиться о их количестве.

“-” Отследить вызовы всех слотов – большая проблема.

Сигналы и слоты в Qt class QButton { … public slots: void clicked();} void MainWindow::on_pushButton_13_clicked() QObject::connect(button_13, clicked, myWindow, on_pushButton_13_clicked) Дэн, ай нид хэлп Вы не видите ничего странного? #include <QObject> class Counter : public QObject { Q_OBJECT public: Counter() { m_value = 0;

} int value() const { return m_value;

} public slots: void setValue(int value);

signals: void valueChanged(int newValue);

private: int m_value;};

Вы не видите ничего странного? #include <QObject> class Counter : public QObject { Q_OBJECT public: Counter() { m_value = 0;

} int value() const { return m_value;

} public slots: void setValue(int value);

signals: void valueChanged(int newValue);

private: int m_value;};

Нет, наследование мы еще не проходили.

А это что? #include <QObject> class Counter : public QObject { Q_OBJECT public: Counter() { m_value = 0;

} int value() const { return m_value;

} public slots: void setValue(int value);

signals: void valueChanged(int newValue);

private: int m_value;};

А это что? Это inline-функция.

Иногда вызов функции стоит дороже самой функции.

Если такую функцию оформить как inline, то вместо генерации кода вызова функции будет подставлено тело функции.

И программа станет чуть-чуть быстрее.

Но есть нюанс Inline-функция не будет считаться компилятором таковой, если она содержит в себе операторы перехода, то есть if, switch, goto , for, while, do while Model-View-Controller Модель – хранит данные.

Отображения – отображают их.

Контроллеры – позволяют вводить данные.

Такая модель позволяет разделять сущности и делать их независимыми.

Спроектируем игру Железная дорога на квадратной сетке.

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

«Юный логистик» Храним карту как двумерный массив структур.

Структура показывает что есть в этой ячейке: есть ли здание, какого вида, что производит, что потребляет, какие ресурсы тут лежат, есть ли железная дорога, в каких направлениях она идет, есть ли паровоз, рельеф квадрата.

Карта умеет всё это хранить, заводить новые объекты, отвечает за производство.

Карта умеет себя отображать.

На действия пользователя реагирует интерфейс, модифицируя карту.

«Юный логистик» Храним карту как двумерный массив структур.

Структура показывает что есть в этой ячейке: есть ли здание, какого вида, что производит, что потребляет, какие ресурсы тут лежат, есть ли железная дорога, в каких направлениях она идет, есть ли паровоз, рельеф квадрата.

Карта умеет всё это хранить, заводить новые объекты, отвечает за производство.

Карта умеет себя отображать.

На действия пользователя реагирует интерфейс, модифицируя карту.

Доба влен ие с ете вого режима н евозмо жно.

«Юный логистик 2.0» Карта хранит информацию о рельефе и дороге, хранит список всех зданий, знает привязку зданий к карте.

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

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

Паровоз знает что на него загружено, где он находится, каков маршрут.

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

Вводит данные с элементов управления.

«Юный логистик 2.1 (несколько игроков)» Надо объектам добавить информацию о их принадлежности.

«Юный логистик 2.2 (сеть)» Надо на место контроллеров добавить объект, который получает информацию из сети.

На место отображения добавить объект, который отправляет информацию в сеть.

Надо создать сервер, который будет помогать обмениваться информацией игрокам.

«Юный логистик 2.3 (сеть+ИИ)» Надо добавить объект, который играет за ИИ.

Информацию он будет получать как отображение, оказывать влияние на поле при помощи контроллеров.

Результаты контрольной Умеют проектировать – 24 человека (17 из С) Не умеют проектировать – 28 человек (12 из С) Не умеют программировать – 11 человек (4 из С) Списывала примерно половина.

Самые интересные ошибки class Cobe{ privat int *x1, *y1, *x2, *y2, z1[MAX_INT], z2[MAX_INT];

Cobe *list, list2[6];

public void add Cube (Cobe &c);};

Самые интересные ошибки person(){ int len=0;

int hight=0;};

Что хотелось увидеть class Cube { Cube();

Cube(const Point &_p1, const Point &_p2, const Point &_p3);

Cube( const Cube &c);

void addCube( const Cube *c);

private: Point p1, p2, p3;

Cube **neighbours;

int neigh_count;};

Что хотелось увидеть class Cube;

struct CubesList {Cube *cub;

CubeList *next;};

class Cube {… private: float x, y, z, size, angle1, angle2;

CubeList neighbours;};

Что хотелось увидеть class Cube {… private: int id;

int *neighbours;

int neigh_size;};

Результаты контрольной Умеют проектировать – 14 человек Не умеют проектировать – 25 человек Не умеют программировать – 6 человек Списывала примерно половина.

Самые интересные ошибки class ClassName{ privet: int x1, y1, x2, y2, r1, r2;

public void interception( /* совсем ничего?*/) {writeln (“ищем пересечение”);

}};

Что хотелось увидеть class Circle {public: Circle();

Circle(float x, float y, float r);

Circle( const Circle &c);

bool intersection( const Circle &c);

private: float center_x, center_y, radius;};

Да, у них было проще Садись в ногах, правды нет.

Лекция 4 Перегрузка операторов Некоторые классы умеют так QString str1, str2;

std::ofstream fil(“file.txt”);

str1=“asdfgh”;

str2=“qwerty”;

str1+=str2;

str2=str1+”zxcvbn”;

fil<<“text1\n”;

Но, черт возьми, как? Ответ Мы имеем возможность перегружать операторы + - * / % += -= *= /= %= +a -a ++a a++ --a a-- && || ! & | ~ ^ &= |= ^= << >> <<= >>== == != < > >= <= &a *a a-> a->* a.* () [] (type), sizeof new, new[] delete, delete [] И еще некоторые А как именно? Функция называется operator @ , где @ - один из перечисленных выше операторов class MyClass { int a;

public: MyClass();

MyClass(int d) { a=d;

} MyClass & operator += (const MyClass &obj);

int getA( return a;

}};

А как именно? MyClass& MyClass::operator += (const MyClass &obj){ a+=obj.getA();} main() { MyClass a(1), b(2);

a+=b;} Но есть нюанс Некоторые операторы надо оформлять так, как надо.

Но есть нюанс MyClass & MyClass::operator = (const MyClass &obj) {// some code here return *this;} Если сделать MyClass operator = (const MyClass &obj);

То вернется копия объекта и a=b=c;

не будет работать.

Но есть нюанс MyClass MyClass::operator + (const MyClass &obj) { MyClass tmp(*this);

tmp+=obj;

return tmp;} Если сделать MyClass &operator + (const MyClass &obj) то вернется копия ссылка на объект, который уничтожается при выходе из функции.

Но есть нюанс MyClass MyClass::operator + (const MyClass &obj) { MyClass tmp(*this);

tmp+=obj;

return tmp;} Если сделать return *this+=obj;

то мы поменяем себя, а этого делать не надо.

Но есть нюанс MyClass MyClass::operator - () // унарный минус { MyClass tmp(-a);

return tmp;} Но есть нюанс MyClass &MyClass::operator -- () // префиксный { a--;

return *this;} MyClass &MyClass::operator -- (int) // постфиксный { a--;

return *this;} В итоге a += b + c - d;

станет MyClass tmp1(b);

tmp1 += c;

MyClass tmp2(tmp1);

delete tmp1;

MyClass tmp3(tmp2);

tmp3 -= d;

MyClass tmp4(tmp3);

delete tmp3;

delete tmp2;

a += tmp4;

delete tmp4;

Семантика переноса MyClass MyClass::operator + (MyClass &&obj) {obj+=*this;

return obj;} Только MyClass operator - (MyClass &&obj) так написать не получится.

И MyClass MyClass::operator + (const MyClass &obj) тоже должен быть В итоге a += b + c - d;

станет MyClass tmp1(b);

tmp1 += c;

MyClass tmp3(tmp1);

tmp3 -= d;

delete tmp1;

a += tmp3;

delete tmp3;

Но мы тратим свое время на переписывание кода и даже иногда копируем его.

Зато он работает быстрее.

Операторы вне класса // Этот код пишется вне класса MyClass operator - (const MyClass &o1, const MyClass &o2) { MyClass tmp(o1);

return tmp-=o2;} Операторы вне класса // Иногда надо сделать так MyClass operator - (const MyClass &o1, const MyClass &o2) { MyClass tmp;

tmp.a = o1.getA() - o2.getA();

return tmp;} // …, но оно не будет компилироваться, // так как нет доступа к tmp.a Друзья класса class myclass2;

class myclass1{ friend void myfunc(myclass1 c1, myclass2 c2, int val);

};

class myclass2{ friend void myfunc(myclass1 c1, myclass2 c2, int val);};

void myfunc(myclass1 c1, myclass2 c2, int val){ // Some code};

Друзья класса «Я такой социопат и у меня нет друзей, потому что друзья нарушают принцип инкапсуляции.» http://bash.im/quote/405212 Параметры по умолчанию C++ позволяет создавать функции, в которых часть параметров может принимать значение по умолчанию.

Значение по умолчанию могут принимать только последние параметры функции.

Параметры по умолчанию float mypaw(float x, int p=2) {float res=1;

for( int i=1;

i<=p;

i++ ) res*=x;

return res;} main() {float x, res1, res2;

… res1 = mypow(x);

// == mypow(x, 2) res2 = mypow(x, 5);} Параметры по умолчанию void somef(float x, int v1=1, float v2=3.5) {// Some code.} main(){ somef(xx);

// верно somef(xx, 2);

// верно somef(xx, 3, 1.45);

// верно somef(xx, 1.45);

// неверно!} Параметры по умолчанию НАДО НАПИСАТЬ, ЧТО В КЛАССЕ ЗНАЧЕНИЕ ПО УМОЛЧАНИЮ ПИШЕТСЯ ТОЛЬКО В ОБЪЯВЛЕНИИ, НО НЕ В ОПИСАНИИ.

Параметры по умолчанию Запрещено иметь функции с одинаковыми названиями и отличающиеся лишь …

• типом параметров по умолчанию;

• количеством параметров по умолчанию;

• значениями параметров по умолчанию.

Параметры по умолчанию Это удобно когда …

• в большинстве случаев данная функция делает одно и тоже действие (можно сэкономить на написании передаваемого параметра);

• хочется визуально различать вызовы функции (например, начало работы и промежуточные стадии);

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

Внимание, конкурс! http://samag.ru/news/more/1692 Кто наберет 150 баллов и выше, получит дополнительный балл в модуле.

Кто получит больше 75 баллов, тот получит 0,5 балла.

Не забывайте писать откуда вы! LMS работает странно Я выбираю klyshinsky.itas.miem.edu.ru Раздел «Программирование (5 семестр)» Давайте немного попишем Нет, не контрольная 1.Насколько понятны лекции (1-5).

2.Сложность семинарских занятий (1-5).

3.Сложность лабораторных работ (1-5).

4.Что бы вы хотели услышать в рамках данного курса? 5.Ваши пожелания по улучшению преподавания лекций.

6.Ваши пожелания по семинарским занятиям и лабораторным работам.

Результаты опроса

• Всё круто

• Всё замечательно!

• Всё отлично

• Всё на высшем уровне

• ЛЕКТОР БОГ ПРОГРАММИРОВАНИЯ Результаты опроса

• Рассказывать помедленнее

• Говорить погромче

• Более подробно объяснять материал с более наглядными примерами.

• Больше полезного материала

• Больше примеров

• Более основательно подходить к преподаваемому материалу, мало что воспринимается по ходу лекции Результаты опроса

• Интерфейсы в Qt (полный разбор конкретных задач)

• Публикация лекций – FIXED

• Больше лекций, доп.

занятия по С++ для тех, кто путается в основном.

(К Вострикову на лекции уже ходили?)

• Ссылки на ресурсы, расширить курс до ObjectiveC (они почти одинаковые) Результаты опроса

• Записывать видео и выкладывать в LMS

• Меньше шутить С видео – всё в ваших руках.

Результаты опроса

• Если Вы спрашиваете, понятно ли нам или нет, а мы молчим - тогда объясните нам еще раз.

Результаты опроса

• Объяснения!!! Простите, но в аудиторию приходят не только те, кто всё знает, но и те, кто хочет чему-то НАУЧИТЬСЯ! А если мы ничего не понимаем, как мы можем это сделать? Самообучение - единственный вариант.

Но даже так сложно.

:( И интерфейс нормально объясните.

(ДА, МЫ ТУПЫЕ)! Лекция 6 Наследование Продолжим наши игры В игре должны быть производственные и оборонительные здания.

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

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

У всех у них есть координаты, здоровье, все они умеют рассчитывать маршрут.

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

Что же делать? Использовать наследование! Как это делать? class First // Базовый класс.

{public: int a, b;

void f1();};

class Second: First // Second наследуется от First.

{public: double c, d;

int f2();

};

// Теперь у него есть 4 свойства и 2 метода.

Зачем это нужно? 1.Несколько классов могут быть частными случаями родительского класса (как торговые, так и военные здания являются зданиями).

Как следствие они обязаны обладать одним и тем же базовым набором свойств и поведением.

2.Мы гарантируем, что у всех классов- наследников, есть определенный набор методов.

3.Разные классы-наследники удобно считать объектами базового класса, ведь у них есть одинаковые свойства и методы.

Зачем это нужно (1)? class Unit { public: Unit();

Unit(int _x, int _y, std::string _name);

~Unit();

void move();

void getPosition(int &_x, int &_y);

private: int x, y;

std::string name;};

Зачем это нужно (1)? class TradeUnit : Unit { public: TradeUnit();

TradeUnit(int _x,int _y,std::string _name);

~TradeUnit();

void loadGoods(const Goods &gd);

Goods unloadGoods(int pos);

Goods getGoods(int pos);

int getGoodsCount() {return goodsCount;} private: int goodsCount;

Goods *storage;};

Зачем это нужно (1)? class MilitaryUnit : Unit { public: MilitaryUnit();

MilitaryUnit(int _x, int _y, std::string _name);

~MilitaryUnit();

void fight();

private: int health;

// И еще много свойств и методов.};

Интерфейс (2) class Stream { public: void operator <<(int);

void operator >>(int);

void operator <<(double);

void operator >>(double);};

Интерфейс (2) class NetworkStream : Stream { public: void operator <<(int);

void operator >>(int);

void operator <<(double);

void operator >>(double);

bool openConnection(std::string);

bool closeConnection();

// And so on.};

Интерфейс (2) class FileStream : Stream { public: void operator <<(int);

void operator >>(int);

void operator <<(double);

void operator >>(double);

bool openFile(std::string);

bool closeFile();

// And so on.};

Типичные ошибки class Point { public: void setPosition(int _x, int _y);

void getPosition(int &_x, int &_y);

private: int x, y;};

class Unit : Point { …};

Теперь можно сделать unit1.setPosition(-1, -1), то есть телепортировать юнит.

Типичные ошибки При проектировании структуры классов можно выделить общие фрагменты в классах и реализовать их один раз в родительском классе.

Но обычно это дурной тон! Следует различать наследование и владение.

Типичные ошибки class Unit { public: Unit(int _x, int _y, std::string _name);

void move();

private: Point pt;};

В данном случае подразделение двигается как это описано в логике его поведения.

Инициализация объектов Unit::Unit() {x=0;

y=0;

name=“”;} Unit::Unit(int _x, int _y, std::string _name) {x=_x;

y=_y;

name=_name;} MilitaryUnit::MilitaryUnit() { health=0;

} MilitaryUnit::MilitaryUnit(int _x, int _y, std::string _name) {x=_x;

y=_y;

name=_name;

health=0;} Инициализация объектов При вызове конструктора сперва вызываются конструкторы базовых классов и лишь после них конструктор данного класса.

MilitaryUnit mu1;

Превращается в mu1.Unit::Unit() {x=0;

y=0;

name=“”;} mu1.MilitaryUnit::MilitaryUnit() { health=0;

} Инициализация объектов При вызове конструктора сперва вызываются конструкторы базовых классов и лишь после них конструктор данного класса.

MilitaryUnit mu1(10, 10, “unit1”);

Превращается в mu1.Unit::Unit() {x=0;

y=0;

name=“”;} mu1.MilitaryUnit::MilitaryUnit(10, 10, “unit1”) {x=10;

y=10;

name=“unit1”;

health=0;} Инициализация объектов Unit::Unit() {x=0;

y=0;

name=“”;} Unit::Unit(int _x, int _y, std::string _name) {x=_x;

y=_y;

name=_name;} MilitaryUnit::MilitaryUnit() { health=0;

} MilitaryUnit::MilitaryUnit(int _x, int _y, std::string _name) : Unit(_x, _y, _name) { health=0;

} Инициализация объектов MilitaryUnit mu1(10, 10, “unit1”);

Превращается в mu1.Unit::Unit(){x=0;

y=0;

name=“”;} mu1.MilitaryUnit::MilitaryUnit(10, 10, “unit1”) { health=0;

} Инициализация объектов Unit::Unit() {x=0;

y=0;

name=“”;} Unit::Unit(int _x, int _y, std::string _name) {x=_x;

y=_y;

name=_name;} MilitaryUnit::MilitaryUnit() { init();

} MilitaryUnit::MilitaryUnit(int _x, int _y, std::string _name) : Unit(_x, _y, _name) { init();

} void MilitaryUnit::init() { health=0;

} // Так лучше Зоны видимости Иногда необходимо сделать так, чтобы даже наследник не имел доступа к части данных.

Для этого используется private.

Если мы хотим позволить дочернему классу иметь доступ к данным родителей, нам следует использовать модификатор доступа protected.

Зоны видимости Также можно изменять вид наследования: private или public.

По умолчанию – private.

private protected public private protected public private- private protected Зоны видимости class MilitaryUnit : public Unit // Так правильнее { public: MilitaryUnit();

MilitaryUnit(int _x, int _y, std::string _name);

~MilitaryUnit();

void fight();

private: int health;

// И еще много свойств и методов.};

Перегрузка функций void Unit::move() {// Просто юнит не передвигается!} void MilitaryUnit::move() {// Поведение войск несколько иное.

switch(orders) { case guard: // Stay here // And so on }} Перегрузка функций main(){ Unit unit;

MilitaryUnit *munit=new MilitaryUnit;

munit->move();

// Корректно перемещает юнит.

unit.move();

// Ничего не делает.

((Unit*)munit)->move();

// Ничего не делает.

// ^^^^^ Это корректное преобразование типов.} Виртуальные функции Предположим, что мы создали несколько классов на основе класса Unit.

Unit MilitaryUnit TradeUnit CivilUnit Battleship Galley Infantry Chivalry Cart Clipper sluggard Виртуальные функции class TheGame{ private: // Мы ведь хотим, чтобы каждый объект вел себя // корректно, а для этого надо знать тип.

Battleship *btlships;

int bshipCount;

Chivalry *chivs;

int ChCount;

// И так сто раз.} Ах, как было бы здорово, … … если бы каждый объект знал, какого он типа, и вызывал правильную функцию move() даже после преобразования типов.

Тогда всех можно было бы хранить как Unit*.

Есть такая партия! Это виртуальные функции.

class Unit{ // some code virtual void move();

// more code};

Виртуальные функции class MilitaryUnit : public Unit { // … virtual void move();

// Будет сделана реализация};

class Chivalry : public MilitaryUnit { // … virtual void move();

// Везде надо писать virtual};

Виртуальные функции main(){ Unit unit;

Chivalry *chiv=new Chivalry;

chiv->move();

// Корректно перемещает юнит.

unit.move();

// Ничего не делает.

((Unit*) chiv)->move();

// Всё равно перемещает.

// ^^^^^ Это корректное преобразование типов.

((Unit*) chiv)->Chivalry::move();

// Всё равно перемещает.} Виртуальные функции class TheGame{ void moveAll();

private: // Сейчас для каждого объекта будет вызываться // правильный move.

Unit **allUnits;

// Именно массив указателей.

int unitsCount;} Виртуальные функции void TheGame::moveAll(){ for( int i=0;

i<unitsCount;

i++ ) allUnits[i]->move();

// Сами разберутся} Абстрактные функции На самом деле не существует такого объекта, как Unit.

Ну или не должно существовать.

Хорошо бы запретить создание таких объектов.

Абстрактная функция, это функция, у которой нет реализации.

Абстрактный класс, это класс, у которого есть абстрактные функции.

Создавать объекты абстрактных классов запрещено.

Более правильное решение enum UnitKind={ukNone,ukChivalry,ukGalley /*, …*/};

class Unit{ public: UnitKind getKind() { return kind;

};

virtual void move()=0;

private: UnitKind kind;};

// Наследуем от Unit класс MilitaryUnit, а от него // класс Chivalry и остальные Более правильное решение Chivalry::Chivalry() {// … kind=ukChivalry;} Galley::Galley() {// … kind=ukGalley;} Новые возможности В 11-м стандарте С++ добавлены две новых возможности: override и final.

override применяется при перегрузке виртуальных функций.

final показывает, что наследование от класса или перегрузка функции запрещены.

Пример struct B {virtual void some_func();

virtual void f(int);

virtual void g() const;};

struct D1 : public B {void sone_func() override;

// неверное имя функции void f(int) override;

// OK virtual void f(long) override;

// несоответствие типа virtual int f(int) override;//несоответствие возв.

типа virtual void g() const final;

// OK virtual void g(long);

// OK: новая виртуальная функция};

struct D2 : D1 {virtual void g() const;

// замещение финальной функции};

Пример 2 struct F final{ int x, y;};

struct D : F // ошибка: наследование от final классов запрещено{ int z;};

Лекция 5 Standard Template Library Пространство имен file1.hpp int value(){ return 5;} file2.hpp const double pi=3.1416 int value(){ return 2*pi;} file3.cpp #include <file1.hpp> #include <file2.hpp> int i=value();

// ? Ичтовызовется Пространство имен file1.hpp namespace space1{ int value(){ return 5;}} file2.hpp namespace space2{ const double pi=3.1416 int value(){ return 2*pi;}} Пространство имен file3.cpp #include <file1.hpp> #include <file2.hpp> int i=space1::value();

// file1.hpp int j=space2::value();

// file2.hpp Пространство имен file3.cpp #include <file1.hpp> #include <file2.hpp> using namespace space1;

int i=value();

// file1.hpp using namespace space2;

int j=space2::value();

// file2.hpp // space2:: , Безбылабыошибкатаккак .

опятьнепонятнокоговызывать Библиотека ввода/вывода Консольный ввод/вывод Данные классы предназначены для работы с консолью – специальными потоками данных, перенаправляемых с клавиатуры или в окно консольной программы.

Класс istream Форматированный ввод istream& operator>> (bool& val);

istream& operator>> (short& val);

istream& operator>> (unsigned short&
English     Русский Правила