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

Содержание

Программирование 5, 6 модули (Объектно-ориентированное программирование) МИЭМ НИУ ВШЭ, Клышинский Э.С. 2013 г.

Слайд 1Здравствуйте!
Меня зовут Клышинский Эдуард Станиславович

eklyshinsky@hse.ru


Слайд 2Программирование 5, 6 модули
(Объектно-ориентированное программирование)
МИЭМ НИУ ВШЭ, Клышинский Э.С.
2013 г.


Слайд 3Рекомендуемая литература
М. Шлее Qt 4.8. Профессиональное программирование на C++ (655 руб.)
Б.

Страуструп Программирование. Принципы и практика использования C++ (2560 руб.)
С. Прата Язык программирования C++ (C++11). Лекции и упражнения (1909 руб.)
http://www.cplusplus.com/
http://habrahabr.ru/


Слайд 4Введение
Как мы будем жить


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

вопросы и понять ответы
Ха (лекции) – ученик постоянно совершенствует свою технику и спрашивает «Почему?»
Ри (курсовая) – ученик постоянно экспериментирует, смешивает техники, пробует разработать собственный стиль.

Слайд 6Жизненная философия
У нас нет времени делать это последовательно!


Слайд 7Как быть хорошим программистом
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


Слайд 8Как быть хорошим программистом
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


Слайд 9Как быть хорошим программистом
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


Слайд 10Что нам предстоит
Лекции
Семинары
Лабораторные работы (5 модуль):
Разработка контейнера.
Визуальный интерфейс для разработанного

контейнера, сохранение.
Контейнер для базового класса.
Разработка большого приложения.

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

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

Старосты! Нам нужны актуальные списки!

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

Наличие обоснованных

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

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

К плохим – DeadLine.


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

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

Слайд 15Система оценок
Лабораторные работы, выполненные в противоречии правилам хорошего тона
НЕ ПРИНИМАЮТСЯ!!!


Слайд 16Система оценок
Если сумма баллов за ниже 4 баллов, берется целая часть

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

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

кода по выбранной теме.
Требования на «отлично»:
классы
наследование
перегрузка операторов
шаблоны
полиморфизм

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

выбранной теме.
Требования на «хорошо»:
классы
наследование

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

выбранной теме.
Требования на «удовлетворительно»:
классы

Слайд 20Лекция 1,2

Основные понятия


Слайд 21Иерархия языков
Процедурное программирование
Ассемблер
Структурное программирование
Объектно-ориентированное программирование
Что понимает компьютер.
Как человеку проще записывать действия.
Как

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

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


Слайд 22Понятие объекта и класса
Весь мир состоит из объектов, поэтому человеку проще

манипулировать именно объектами, а не наборами переменных.

Слайд 23Понятие объекта и класса
Что объединяет эти вещи?


Слайд 24Понятие объекта и класса
Стул — мебельное изделие для сидения одного человека, со

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


Слайд 25Понятие объекта и класса
Стул — мебельное изделие для сидения одного человека, со

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

Это свойства объекта


Слайд 26Понятие объекта и класса
Стул — мебельное изделие для сидения одного человека, со

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

Это функциональность объекта


Слайд 27Понятие объекта и класса


Класс = данные + методы работы с ними


Слайд 28Понятие объекта и класса
Эйдос Платона - то подлинное, что дается в

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



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

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



Слайд 30Понятие объекта и класса
Класс (шаблон)
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);
};

объекты (данные)

методы


Слайд 31Абстракция
Буч Г. Объектно-ориентированный анализ и проектирование


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

она. - Они рисовали мышеловки, месяц, математику, множество... Ты когда-нибудь видела, как рисуют множество?
- Множество чего? - спросила Алиса.
- Ничего, - отвечала Соня. - Просто множество!
- Не знаю, - начала Алиса, - может...
- А не знаешь - молчи, - оборвал ее Болванщик.

Слайд 33

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

она. - Они рисовали мышеловки, месяц, математику, множество... Ты когда-нибудь видела, как рисуют множество?
- Множество чего? - спросила Алиса.
- Ничего, - отвечала Соня. - Просто множество!
- Не знаю, - начала Алиса, - может...
- А не знаешь - молчи, - оборвал ее Болванщик.

Кстати, это не наши методы. Лучше задавайте вопросы.


Слайд 34Классом может быть и абстрактная сущность
Множество
Свойства: массив элементов, количество элементов в

массиве

Методы: добавить элемент, удалить элемент, очистить, выбрать элемент, найти элемент


Слайд 35Классом может быть и абстрактная сущность
Заслуга
Свойства: дата, место, наименование

Методы: отобразить, установить

дату (в целях проверки корректности входных данных), вернуть дату


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


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


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

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

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

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

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

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

int methodFoo(int a, char *b); // методы
float methodBar();
};

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

property2, property3;
int methodFoo(int a, char *b); // методы
int property1; // свойства класса
float methodBar();
};

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


// Да, как и форматирование кода

Слайд 43Синтаксис
int TheClassName::methodFoo(int a, char *b)
{
property3=a; property1=strlen(b);
return

0;
}

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

Слайд 44Синтаксис
#include “myclass.h”

int main()
{TheClassName obj1, *obj2=&obj1;

obj1.property1=0;
obj1.methodBar();
obj2->methodFoo(10, “строка”);
}


Слайд 45Синтаксис
class TheClassName2 //
{
public:
TheClassName *objects;
int count;

void

add(TheClassName &obj);
void delete(int pos);
};

Слайд 46Синтаксис
class TheClassName2 //
{
public:
TheClassName *objects;
int count;

void

add(TheClassName &obj);
void delete(int pos);
};

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


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

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

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


Слайд 48Область видимости
По умолчанию свойства и методы класса являются private, поэтому забыв

написать public мы лишаем класс интерфейса.

Структура – тоже класс и она может иметь методы. В целях совместимости все ее члены и методы по умолчанию public.


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

обязано быть private.


Пожалейте других разработчиков!



Слайд 50Область видимости
Общее правило.
Правила хорошего тона предписывают описать сперва открытые члены класса,

а потом закрытые.

Пожалейте других разработчиков!



Слайд 51Пример
Мы пишем экономическую стратегию (игра). Необходимо создать класс, описывающий источник ресурсов.
Время

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


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

число работников, максимальное число работников.

Методы: прошло время


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

ресурса
// Сколько есть ресурса, сколько произведено
int overall, produced;
// Число работников, мах число работников
int workerCount, maxWorkerCount;
// Тикает время
bool tick();
};


Слайд 54Пример
bool Mine::tick()
{double tmp;
curTime++;
if( curTime>=interval )
{curTime

= 0;
tmp = ((double) workerCount) /
maxWorkerCount;
produced += productivity * tmp;
return true;
}
return false;
}


Слайд 55Пример использования
int main()
{Mine mn;

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

И кого будут ругать?


Слайд 56Первый принцип программиста
КРУГОМ ВРАГИ!

Пишите код так, как будто сопровождать его будет

склонный к насилию психопат, который знает, где вы живете.
(с) Стив Макконнелл

Слайд 57Второй принцип программиста
Надо инициализировать переменные

Буратино дали пять яблок, сколько яблок у

него стало?

Неизвестно, так как неизвестно, сколько яблок у него было до того.


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

(Раз уж мы

об этом заговорили.)


Слайд 59Четвертый принцип программиста

КОПИРОВАНИЕ – ЗЛО!

(Раз уж мы об этом заговорили.)


Слайд 60Как быть?
Принцип 1 вступает в противоречие с принципом 2. Мы не

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


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

Но наши коллеги

забудут ее вызвать. ☹


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

создании объекта.

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

уничтожении объекта.

Слайд 64Пример
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();

Слайд 65Пример

private:
char *resName; // Имя ресурса
// Сколько есть ресурса, сколько

произведено
int overall, produced;
// Число работников, мах число работников
int workerCount, maxWorkerCount;
};


Слайд 66Пример
Mine::Mine()
{resName=NULL;
overall=0;
produced=0;
workerCount=0;
maxWorkerCount=0;
// И так далее
}


Слайд 67Пример
Mine::Mine(char *name, int amount, int prdctvt,

int intrvl)
{resName=new char [strlen(name)];
overall=amount;
produced=0;
workerCount=0;
maxWorkerCount=0;
// И так далее
}


Слайд 68Пример
bool Mine::addWorker()
{if( workerCount == maxWorkerCount )
return false;
workerCount++; return

true;
}

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


Слайд 69Пример
int main()
{Mine mine1;
Mine mine2(“Mine2”, 100, 1, 50);
Mine mine3(mine2);

// Дальше

идет код
}

Слайд 70Выделение памяти
Функция malloc ничего не должна знать про конструктор и деструктор,

она только выделяет память. Поэтому используется оператор new.

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

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

Слайд 71Выделение памяти


Mine *newMine, *mine2, *mine3;

newMine=new Mine;
newMine->addWorker();


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

( параметры );

Mine *newMine, *mine2, *mine3;

newMine=new Mine;
newMine->addWorker();
mine2=new Mine(newMine);
mine3=new Mine(“Mine3”, 900, 2, 30);


Слайд 73Выделение памяти
int **arr;
int cnt, i, j;

scanf(“%d”, cnt);
arr=new int * [cnt];
for( i=0;

i{arr[i]=new int[cnt];
for( j=0; j arr[i][j]=i+j;
}

Слайд 74Освобождение памяти
Функция free ничего не знает про деструктор, поэтому надо пользоваться

delete.

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

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


Слайд 75Освобождение памяти
Внимание!
Всё, что выделялось с квадратными скобками с ними же и

удаляется!

delete null; или delete [] null;
Это работает!


Слайд 76Конструктор вызывается
… при любом создании объекта:
создании переменной (локальной или глобальной –

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


Слайд 77Деструктор вызывается
… при любом уничтожении объекта:
закончилось время жизни (зона видимости) переменной

(локальной или глобальной – не важно);
освобождении динамически выделенной памяти (использование delete);
передаче параметра-объекта в функцию (после возвращения из функции);
удалении временного объекта для вычисления результата (после вычислений);


Слайд 78Для временных переменных


… для снятия копии вызывается копирующий конструктор.

Если его

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

Слайд 79Пример
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);
// Еще код
}


Слайд 80Пример
void func2()
{Stack s;

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


Слайд 81Чему учит нас Летающий Макаронный Монстр?


9. Лучше бы ты не передавал

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

Слайд 82Значит передавать по ссылке?

-- Кристофер Робин, ты должен сбить шар из

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

Слайд 83Да, но только по константной

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;
};


Слайд 84Да, но только по константной

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;
};


Слайд 85Переменная видна с момента ее объявления до соответствующей закрывающей скобки
Область видимости

переменной

Слайд 86int Stack::push(int d)
{int i, t;
int *tmp;
tmp=new int[count+1];
for( i=0;

i {t=data[i]
tmp[i]=t;
}
tmp[count++]=d;
delete [] data;
data=tmp;
}

Переменная видна с момента ее объявления до соответствующей закрывающей скобки

Область видимости переменной


Слайд 87int Stack::push(int d)
{int i;
int *tmp;
tmp=new int[count+1];
for( i=0; i

i++ )
{int t=data[i]
tmp[i]=t;
}
tmp[count++]=d;
delete [] data;
data=tmp;
}

Переменная видна с момента ее объявления до соответствующей закрывающей скобки

Область видимости переменной


Слайд 88int Stack::push(int d)
{
int *tmp;
tmp=new int[count+1];
for( int i=0; i

i++ )
{int t=data[i]
tmp[i]=t;
}
tmp[count++]=d;
delete [] data;
data=tmp;
}

Переменная видна с момента ее объявления до соответствующей закрывающей скобки

Область видимости переменной


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

for( sum=0,

i=0; i for( int i=0; i sum+=data[::i][i];
return sum;
}

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

for( sum=0,

i=0; i for( int i=0; i sum+=data[::i][i];
return sum;
}

i из цикла
i верхнего уровня


Слайд 91Лекция 3

Разработка визуальных интерфейсов в Qt


Слайд 92Указатель на функцию


int (*pt2Function)(float, char, char);

pt2Function представляет собой переменную, указывающую на

начало функции, которая возвращает int и принимает float, char и char.


Слайд 93Указатель на функцию
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’);
}


Слайд 94Зачем это надо?
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;
// …
}

Слайд 95Зачем это надо?
void sortMines(Mine *mines, int count, int (*cmpFunc) (const Mine

&m1, const Mine &m2) )
{
for( int i=0; i for( int j=i+1; j if(cmpFunc(mines[i],mines[j])<0)
swapMines(mines[i], mines[j]);
}




Слайд 96Зачем это надо?
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
}



Слайд 97Удобнее так

typedef int (*cmpFuncType) (const Mine &m1, const Mine &m2) );

Теперь

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

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

class MinesCollection
{// Some code here
public:

void setSortingMode(SortModes mode);
void sortMines();
// code
private cmpFuncType ptr;
}

Слайд 99Удобнее так
enum SortModes={smProd, smIntr, smWrk};

void MinesCollection::setSortingMode(SortModes mode)
{ switch( mode )
{case

smProd: ptr=cmpMines1; return;
case smIntr: ptr=&cmpMines2; return;
// А еще добавить по возрастанию или убыванию.
}
}

Слайд 100Для классов
// Взято с 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
};

Слайд 101Для классов
int (TMyClass::*pt2Member)(float, char, char) = null;
int (TMyClass::*pt2ConstMember)(float, char, char) const

= null;

pt2ConstMember = &TMyClass::DoMore;
pt2Member = &TMyClass::DoIt;
// pt2Member может показывать и на &DoMore

Слайд 102Для классов
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;


Слайд 103Давайте немного попишем


Слайд 104Сигналы и слоты в Qt


Слайд 105Вы не видите ничего странного?
#include
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;
};

Слайд 106Вы не видите ничего странного?
#include
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;
};

Слайд 107Сигналы и слоты в Qt

void Counter::setValue(int value)
{
if (value !=

m_value) {
m_value = value;
emit valueChanged(value);
}
}

Слайд 108Сигналы и слоты в 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

Слайд 109Сигналы и слоты в 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

Слайд 110Сигналы и слоты в Qt
“+”
На один сигнал можно «повесить» много слотов.

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

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

Слайд 111Сигналы и слоты в Qt
class QButton
{ …
public slots: void clicked();
}

void

MainWindow::on_pushButton_13_clicked()

QObject::connect(button_13, clicked, myWindow, on_pushButton_13_clicked)


Слайд 112Дэн, ай нид хэлп


Слайд 113Вы не видите ничего странного?
#include
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;
};

Слайд 114Вы не видите ничего странного?
#include
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;
};

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


Слайд 115А это что?
#include
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;
};



Слайд 116А это что?

Это inline-функция.

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

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

Слайд 117Но есть нюанс

Inline-функция не будет считаться компилятором таковой, если она содержит

в себе операторы перехода, то есть

if, switch, goto, for, while, do while

Слайд 118Model-View-Controller
Модель – хранит данные.
Отображения – отображают их.
Контроллеры – позволяют вводить данные.

Такая

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

Слайд 119Спроектируем игру


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

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

Слайд 120«Юный логистик»
Храним карту как двумерный массив структур. Структура показывает что есть

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

Слайд 121«Юный логистик»
Храним карту как двумерный массив структур. Структура показывает что есть

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

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


Слайд 122«Юный логистик 2.0»
Карта хранит информацию о рельефе и дороге, хранит список

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

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


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

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

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

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

Слайд 126Результаты контрольной
Умеют проектировать – 24 человека (17 из С)
Не умеют проектировать

– 28 человек (12 из С)
Не умеют программировать – 11 человек (4 из С)

Списывала примерно половина.

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

list2[6];
public
void add Cube (Cobe &c);

};

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

};


Слайд 129Что хотелось увидеть
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;
};

Слайд 130Что хотелось увидеть
class Cube;
struct CubesList
{Cube *cub;
CubeList *next;
};
class Cube
{…
private:
float

x, y, z, size, angle1, angle2;
CubeList neighbours;
};

Слайд 131Что хотелось увидеть
class Cube
{…
private:
int id;
int *neighbours;
int neigh_size;
};


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

умеют программировать – 6 человек

Списывала примерно половина.

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

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

};

Слайд 134Что хотелось увидеть
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;
};

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


Слайд 136Лекция 4

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


Слайд 137Некоторые классы умеют так
QString str1, str2;
std::ofstream fil(“file.txt”);

str1=“asdfgh”;
str2=“qwerty”;
str1+=str2;
str2=str1+”zxcvbn”;
fil


Слайд 138Но, черт возьми, как?


Слайд 139Ответ
Мы имеем возможность перегружать операторы
+ - * / % += -= *=

/= %= +a -a ++a a++ --a a-- && || ! & | ~ ^ &= |= ^= << >> <<= >>= = == != < > >= <=

&a *a a-> a->* a.* () [] (type) ,  
sizeof
new, new[]
delete, delete []

И еще некоторые


Слайд 140А как именно?
Функция называется operator @ ,
где @ - один из

перечисленных выше операторов

class MyClass
{ int a;
public:
MyClass();
MyClass(int d) { a=d; }
MyClass & operator += (const MyClass &obj);
int getA( return a; }
};

Слайд 141А как именно?
MyClass& MyClass::operator += (const MyClass &obj)
{
a+=obj.getA();
}

main()
{ MyClass a(1),

b(2);

a+=b;
}

Слайд 142Но есть нюанс


Некоторые операторы надо оформлять так, как надо.


Слайд 143Но есть нюанс
MyClass & MyClass::operator = (const MyClass &obj)
{// some code

here
return *this;
}

Если сделать
MyClass operator = (const MyClass &obj);
То вернется копия объекта и
a=b=c;
не будет работать.


Слайд 144Но есть нюанс
MyClass MyClass::operator + (const MyClass &obj)
{ MyClass tmp(*this);
tmp+=obj;

return tmp;
}

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


Слайд 145Но есть нюанс
MyClass MyClass::operator + (const MyClass &obj)
{ MyClass tmp(*this);
tmp+=obj;

return tmp;
}

Если сделать
return *this+=obj;
то мы поменяем себя, а этого делать не надо.

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

return tmp;
}


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

MyClass

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


Слайд 148В итоге 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;

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

Только
MyClass operator - (MyClass

&&obj)
так написать не получится. И
MyClass MyClass::operator + (const MyClass &obj)
тоже должен быть


Слайд 150В итоге a += b + c - d; станет
MyClass tmp1(b);
tmp1

+= c;
MyClass tmp3(tmp1);
tmp3 -= d;
delete tmp1;
a += tmp3;
delete tmp3;

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


Слайд 151Операторы вне класса
// Этот код пишется вне класса
MyClass operator - (const

MyClass &o1, const MyClass &o2)
{ MyClass tmp(o1);
return tmp-=o2;
}


Слайд 152Операторы вне класса
// Иногда надо сделать так
MyClass operator - (const MyClass

&o1, const MyClass &o2)
{ MyClass tmp;
tmp.a = o1.getA() - o2.getA();
return tmp;
}
// …, но оно не будет компилироваться,
// так как нет доступа к tmp.a


Слайд 153Друзья класса
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
};

Слайд 154Друзья класса
«Я такой социопат и у меня нет друзей, потому что

друзья нарушают принцип инкапсуляции.»

http://bash.im/quote/405212


Слайд 155Параметры по умолчанию
C++ позволяет создавать функции, в которых часть параметров может

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

Слайд 156Параметры по умолчанию
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);
}


Слайд 157Параметры по умолчанию
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); // неверно!
}

Слайд 158Параметры по умолчанию
НАДО НАПИСАТЬ, ЧТО В КЛАССЕ ЗНАЧЕНИЕ ПО УМОЛЧАНИЮ ПИШЕТСЯ

ТОЛЬКО В ОБЪЯВЛЕНИИ, НО НЕ В ОПИСАНИИ.

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


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


Слайд 160Параметры по умолчанию
Это удобно когда …
в большинстве случаев данная функция делает

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


Слайд 161Внимание, конкурс!
http://samag.ru/news/more/1692

Кто наберет 150 баллов и выше, получит дополнительный балл в

модуле.
Кто получит больше 75 баллов, тот получит 0,5 балла.
Не забывайте писать откуда вы!

Слайд 162LMS работает странно
Я выбираю
klyshinsky.itas.miem.edu.ru
Раздел «Программирование (5 семестр)»


Слайд 163Давайте немного попишем


Слайд 164Нет, не контрольная
Насколько понятны лекции (1-5).
Сложность семинарских занятий (1-5).
Сложность лабораторных работ

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

Слайд 165Результаты опроса
Всё круто
Всё замечательно!
Всё отлично
Всё на высшем уровне
ЛЕКТОР БОГ ПРОГРАММИРОВАНИЯ


Слайд 166Результаты опроса
Рассказывать помедленнее
Говорить погромче
Более подробно объяснять материал с более наглядными примерами.
Больше

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

Слайд 167Результаты опроса
Интерфейсы в Qt (полный разбор конкретных задач)
Публикация лекций – FIXED
Больше

лекций, доп. занятия по С++ для тех, кто путается в основном.
(К Вострикову на лекции уже ходили?)
Ссылки на ресурсы, расширить курс до ObjectiveC (они почти одинаковые)

Слайд 168Результаты опроса
Записывать видео и выкладывать в LMS
Меньше шутить


С видео – всё

в ваших руках.

Слайд 169Результаты опроса
Если Вы спрашиваете, понятно ли нам или нет, а мы

молчим - тогда объясните нам еще раз.

Слайд 170Результаты опроса
Объяснения!!! Простите, но в аудиторию приходят не только те, кто

всё знает, но и те, кто хочет чему-то НАУЧИТЬСЯ! А если мы ничего не понимаем, как мы можем это сделать? Самообучение - единственный вариант. Но даже так сложно. :( И интерфейс нормально объясните. (ДА, МЫ ТУПЫЕ)!

Слайд 171Лекция 6

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


Слайд 172Продолжим наши игры
В игре должны быть производственные и оборонительные здания. И

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

Слайд 173Продолжим наши игры
Если добавлять эти свойства и методы в разные классы,

значит придется их копировать, а копирование – зло.

Что же делать?

Использовать наследование!


Слайд 174Как это делать?
class First // Базовый класс.
{public:
int a, b;

void f1();
};

class Second: First // Second наследуется от First.
{public:
double c, d;
int f2();
}; // Теперь у него есть 4 свойства и 2 метода.

Слайд 175Зачем это нужно?
Несколько классов могут быть частными случаями родительского класса (как

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

Слайд 176Зачем это нужно (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;
};


Слайд 177Зачем это нужно (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;
};


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

MilitaryUnit(int _x, int _y, std::string _name);
~MilitaryUnit();
void fight();
private:
int health;
// И еще много свойств и методов.
};


Слайд 179Интерфейс (2)
class Stream
{ public:
void operator

>>(int);
void operator <<(double);
void operator >>(double);
};

Слайд 180Интерфейс (2)
class NetworkStream : Stream
{ public:
void operator

void operator >>(int);
void operator <<(double);
void operator >>(double);
bool openConnection(std::string);
bool closeConnection();
// And so on.
};

Слайд 181Интерфейс (2)
class FileStream : Stream
{ public:
void operator

void operator >>(int);
void operator <<(double);
void operator >>(double);
bool openFile(std::string);
bool closeFile();
// And so on.
};

Слайд 182Типичные ошибки
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), то есть телепортировать юнит.

Слайд 183Типичные ошибки

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

и реализовать их один раз в родительском классе.

Но обычно это дурной тон!

Следует различать наследование и владение.

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

void move();
private:
Point pt;
};

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

Слайд 185Инициализация объектов
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;}



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

после них конструктор данного класса.

MilitaryUnit mu1;

Превращается в
mu1.Unit::Unit() {x=0; y=0; name=“”;}
mu1.MilitaryUnit::MilitaryUnit()
{ health=0; }

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

после них конструктор данного класса.

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;}

Слайд 188Инициализация объектов
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; }



Слайд 189Инициализация объектов


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

Превращается в

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


{ health=0; }

Слайд 190Инициализация объектов
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; } // Так лучше



Слайд 191Зоны видимости

Иногда необходимо сделать так, чтобы даже наследник не имел доступа

к части данных. Для этого используется private.

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

Слайд 192Зоны видимости

Также можно изменять вид наследования: private или public.
По умолчанию –

private.



Слайд 193Зоны видимости
class MilitaryUnit : public Unit // Так правильнее
{ public:

MilitaryUnit();
MilitaryUnit(int _x, int _y, std::string _name);
~MilitaryUnit();
void fight();
private:
int health;
// И еще много свойств и методов.
};


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

void MilitaryUnit::move()
{// Поведение войск

несколько иное.
switch(orders)
{ case guard: // Stay here
// And so on
}
}

Слайд 195Перегрузка функций
main()
{
Unit unit;
MilitaryUnit *munit=new MilitaryUnit;

munit->move(); // Корректно перемещает

юнит.
unit.move(); // Ничего не делает.
((Unit*)munit)->move(); // Ничего не делает.
// ^^^^^ Это корректное преобразование типов.
}

Слайд 196Виртуальные функции
Предположим, что мы создали несколько классов на основе класса Unit.
Unit
MilitaryUnit
TradeUnit
CivilUnit
Battleship
Galley
Infantry
Chivalry
Cart
Clipper
sluggard


Слайд 197Виртуальные функции
class TheGame
{
private:
// Мы ведь хотим, чтобы каждый объект вел

себя // корректно, а для этого надо знать тип.
Battleship *btlships;
int bshipCount;
Chivalry *chivs;
int ChCount;
// И так сто раз.
}

Слайд 198Ах, как было бы здорово, …

… если бы каждый объект знал,

какого он типа, и вызывал правильную функцию move() даже после преобразования типов. Тогда всех можно было бы хранить как Unit*.

Слайд 199Есть такая партия!

Это виртуальные функции.

class Unit
{
// some code
virtual void

move();
// more code
};

Слайд 200Виртуальные функции
class MilitaryUnit : public Unit
{ // …
virtual void

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

class Chivalry : public MilitaryUnit
{ // …
virtual void move(); // Везде надо писать virtual
};


Слайд 201Виртуальные функции
main()
{
Unit unit;
Chivalry *chiv=new Chivalry;

chiv->move(); // Корректно перемещает

юнит.
unit.move(); // Ничего не делает.
((Unit*) chiv)->move(); // Всё равно перемещает.
// ^^^^^ Это корректное преобразование типов.
((Unit*) chiv)->Chivalry::move(); // Всё равно перемещает.
}

Слайд 202Виртуальные функции
class TheGame
{
void moveAll();
private:
// Сейчас для каждого объекта будет

вызываться
// правильный move.
Unit **allUnits; // Именно массив указателей.
int unitsCount;
}

Слайд 203Виртуальные функции

void TheGame::moveAll()
{
for( int i=0; imove();

// Сами разберутся
}

Слайд 204Абстрактные функции

На самом деле не существует такого объекта, как Unit. Ну

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

Абстрактная функция, это функция, у которой нет реализации.
Абстрактный класс, это класс, у которого есть абстрактные функции.
Создавать объекты абстрактных классов запрещено.

Слайд 205Более правильное решение
enum UnitKind={ukNone,ukChivalry,ukGalley /*, …*/};
class Unit
{
public:
UnitKind getKind()

{ return kind; };
virtual void move()=0;
private:
UnitKind kind;
};
// Наследуем от Unit класс MilitaryUnit, а от него // класс Chivalry и остальные


Слайд 206Более правильное решение
Chivalry::Chivalry()
{// …
kind=ukChivalry;
}

Galley::Galley()
{// …
kind=ukGalley;
}



Слайд 207Новые возможности
В 11-м стандарте С++ добавлены две новых возможности: override и

final.

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

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

Слайд 208Пример
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; // замещение финальной функции
};

Слайд 209Пример 2
struct F final
{
int x, y;
};

struct D :

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

Слайд 210Лекция 5

Standard Template Library


Слайд 211Пространство имен
file1.hpp
int value(){ return 5;}
file2.hpp
const double pi=3.1416
int value(){ return 2*pi;}

file3.cpp
#include
#include


int i=value(); // И что вызовется?

Слайд 212Пространство имен
file1.hpp
namespace space1
{
int value(){ return 5;}
}
file2.hpp
namespace space2
{
const double pi=3.1416

int value(){ return 2*pi;}
}

Слайд 213Пространство имен
file3.cpp
#include
#include

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



Слайд 214Пространство имен
file3.cpp
#include
#include

using namespace space1;
int i=value(); // file1.hpp
using namespace space2;
int

j=space2::value(); // file2.hpp
// Без space2:: была бы ошибка, так как опять непонятно кого вызывать.


Слайд 215Библиотека ввода/вывода


Слайд 216Консольный ввод/вывод
Данные классы предназначены для работы с консолью – специальными потоками

данных, перенаправляемых с клавиатуры или в окно консольной программы.


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

operator>> (unsigned short& val);
istream& operator>> (int& val);
istream& operator>> (unsigned int& val);
istream& operator>> (long& val);
istream& operator>> (unsigned long& val);
istream& operator>> (long long& val);
istream& operator>> (unsigned long long& val);
istream& operator>> (float& val);
istream& operator>> (double& val);
istream& operator>> (long double& val);
istream& operator>> (void*& val);

Слайд 218Класс istream
Неформатированный ввод
single character
int get();
istream& get (char& c);
c-string
istream& get (char*

s, streamsize n);
istream& get (char* s, streamsize n, char delim);

istream& getline(char* s, streamsize n);
istream& getline(char* s, streamsize n, char delim);

Слайд 219Класс ostream
Форматированный вывод
ostream& operator

short val);
ostream& operator<< (int val);
ostream& operator<< (unsigned int val);
ostream& operator<< (long val);
ostream& operator<< (unsigned long val);
ostream& operator<< (long long val);
ostream& operator<< (unsigned long long val);
ostream& operator<< (float val);
ostream& operator<< (double val);
ostream& operator<< (long double val);
ostream& operator<< (void* val);

Слайд 220Класс istream
Неформатированный ввод
single character

istream& put (char& c);
c-string
Только


Слайд 221Класс istream
Для программы определяются следующие потоки.
cin – консольный ввод (клавиатура).
cout –

консольный вывод (черное окно).
cerr – поток ошибок (окно, в которое выдаются ошибки компилятора).
clog – поток журнала (окно, в которое выдаются сообщения о запуске приложения, потоков, загрузке/выгрузке библиотек, …).

Слайд 222Класс istream
// istream::getline example
#include // std::cin, std::cout

int main

() {
char name[256], title[256];
std::cout << "Please, enter your name:";
std::cin.getline (name,256);
std::cout << «Enter your favorite movie:";
std::cin.getline (title,256);
std::cout << name << "'s favorite movie is " << title;
return 0;
}

Слайд 223Класс ifstream
Конструкторы
ifstream();
explicit ifstream (const char* filename, ios_base::openmode mode = ios_base::in);
explicit ifstream

(const string& filename, ios_base::openmode mode = ios_base::in);
ifstream (const ifstream&) = delete;
ifstream (ifstream&& x);

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

объявление ключевое слово explicit. Это заставляет код использовать параметр правильного типа или привести параметр к правильному типу. То есть, если приведение не выражено в коде явно, возникнет ошибка.

Слайд 225explicit
Заодно приводит следующий код к вызову правильного конструктора.
class cl2
{cl2(int); // Нет

конструктора по умолчанию

};
cl2 v=2;
//Не создает, а потом инициализирует,
// а вызывает правильный конструктор.

Слайд 226Класс ifstream
Режимы открытия файлов


Слайд 227Класс ifstream
Открытие/закрытие
void open (const char* filename, ios_base::openmode mode = ios_base::in);
void

open (const string& filename, ios_base::openmode mode = ios_base::in);
void close();
bool good() const;
bool eof() const;

Слайд 228Класс ifstream/ofstream
Чтение двоичных данных
istream& read (char* s, streamsize n);
Запись двоичных данных
ostream&

write (const char* s, streamsize n);


Слайд 229Класс ifstream
Позиционирование
istream& seekg (streampos pos);
istream& seekg (streamoff off, ios_base::seekdir way);
ios_base::beg beginning of

the stream
ios_base::cur current position in the stream
ios_base::end end of the stream
streampos tellg(); // текущая позиция


Слайд 230Класс ifstream (пример)
// read a file into memory
#include

// std::cout
#include // std::ifstream
int main () {
std::ifstream is ("test.txt", std::ifstream::binary);
if (is) {
is.seekg (0, is.end);
int length = is.tellg();
is.seekg (0, is.beg);

Слайд 231Класс ifstream (пример)
char * buffer = new char [length];

is.read (buffer,length);
is.close();
std::cout.write (buffer,length);
delete[] buffer;
}
return 0;
}

Слайд 232Класс ifstream (пример)
int *buffer= new

char [length/sizeof(int)];
is.read ((char*)buffer,length);
is.close();

delete [] buffer;
}
return 0;
}

Слайд 233Сериализация объектов
class Unit
{
UnitKind getKind() { return kind; };
virtual void

write(ofstream &file)=0;
virtual void read(ifstream &file)=0;
virtual void move()=0;
private:
UnitKind kind;
};

Слайд 234Сериализация объектов
class Infantry: Unit
{

virtual void write(ofstream &file);
virtual void read(ifstream

&file);
virtual void move();
private:
float shield, force, health;
};

Слайд 235Сериализация объектов
void Infantry::write(ofstream &file)
{
file

force << ”, ” << health << ”\n”;
};
// Текстовый случай
void Infantry::read(ifstream &file)
{char c;
file >> shield >> c >> force >> c >> health >> c;
};


Слайд 236Сериализация объектов
void Infantry::write(ofstream &file)
{
file.write((char*)&shield,sizeof(float));
file.write((char*)&force,sizeof(float));
file.write((char*)&health,sizeof(float));
};
// Бинарный случай (совпадение имен!)
void Infantry::read(ifstream &file)
{file.read((char*)&shield,sizeof(float));
file.read((char*)&force,sizeof(float));

file.read((char*)&health,sizeof(float));
};


Слайд 237Класс ifstream
class UnitCollection
{

void write(std::string filename);
void read (std::string filename);

};


Слайд 238Класс ifstream
… ::write(std::string filename)
{std::ofstream ofile(filename);
int tmp;
ofile.write((char*)&ucnt, sizeof(int));
for( int

i=0; i {tmp=units[i]->getKind()
ofile.write((char*)&tmp, sizeof(int));
units[i]->write(ofile);
}
}

Слайд 239Класс ifstream
… ::read(std::string filename)
{std::ifstream ifile(filename);
int tmp;
ifile.read((char*)&ucnt, sizeof(int));
units=new Unit*[ucnt];

for( int i=0; i {ifile.read((char*)&tmp, sizeof(int));
if(tmp==utInf) units[i]=new Infantry; else if(tmp==utChiv) units=new Chival;

units[i]->read(ifile);
} }

Слайд 240Класс ifstream
ifstream &operator >> (ifstream &file, Infantry &data)
{data.read(file);
return file;
}

ofstream &operator

<< (ofstream &file, Infantry &data)
{data.write(file);
return file;
}


Слайд 241Класс ifstream
ifstream &operator >> (ifstream &file, Infantry &data)
{data.read(file);
return file;
}

ofstream &operator

<< (ifstream &file, Infantry &data)
{data.write(file);
return file;
}


Слайд 242Класс ifstream

} // STL


Слайд 243Что нас ждет в конце модуля?
Две лабораторные работы (1 и 2

балла соотв.):
использование контейнеров STL в консоли;
разработка собственного контейнера и работа с ним в оконном приложении.
Курсовик (2 балла):
постановка задачи, правила работы (игры),
метод решения задачи ((выигрышная) стратегия),
фрагменты кода.
Зачет: письменная работа на 1,5 часа (5 баллов).

Слайд 244Разбор полетов, мысли
В любом случае, вам необходимо больше работать самостоятельно.
Это слишком

сложно?
http://www.youtube.com/watch?v=KkMDCCdjyW8
Самое интересное начинается после 5:30.


Слайд 245Разбор полетов, мысли
В любом случае, вам необходимо больше работать самостоятельно.
Это слишком

сложно?
http://www.cse.unt.edu/~rada/CSCE5290/


Слайд 246Перспективы
Все пересдачи после зимней сессии.
Если Вы не сдали как зачет, так

и экзамен – это только один долг.
Если Вы не сдали экзамен и Вас за это не отчислили, то (¡кажется, т.е. до подтверждения учебным офисом это личное мнение лектора!) Вам придется прослушать этот курс еще раз за дополнительные деньги.

Слайд 247Перспективы
Лабораторные работы:
Сериализация (чтение/запись файлов с использованием библиотеки STL) – переделать имеющийся

у вас контейнер так, чтобы он имел возможность сохранять информацию в файл и считывать ее оттуда. (1 балл)
Хранение произвольных типов – переделать имеющийся контейнер с использованием шаблонов (