Д.з. на 3 марта Язык С++ - занятие 41
Задача 1: треугольный массив int* a[10]; // Создаем.. for (int i = 0; i
Задача 3: двоичный поиск Делим массив пополам Смотрим, в какой половине граница четных и нечетных Повторяем то же с этой половиной И так в цикле, пока длина куска массива > Язык С++ - занятие 43
Задача 3: код // Предполагаем, что: длина массива > 1, сначала идут несколько // (>=1) четных чисел, потом несколько (>=1) нечетных int numEven(int* a, int size) { int beg = 0, end = size - 1; while (end - beg > 1) { int mid = (beg + end) / 2; if (a[mid]%2 == 0) beg = mid; else end = mid; } return end;// Тут всегда будет end - beg == 1 } // Пример вызова int a[10]; … cout
Д.з. на 10 марта Язык С++ - занятие 45
Задача 1: order // Вспомогательная функция: // Упорядочиваем два числа void order(int& x, int& y) { if (x > y) { int tmp = x; x = y; y = tmp; } } void order(int& x, int& y, int& z) { order(x, y); order(x, z); order(y, z); } // Пример вызова: int a = 3, b = 1, c = 2; order(a, b, c); cout
Задача 2: Стек фиксированного размера class stack { int stk[100]; int size; public: stack() : size(0) {} void push(int i) { stk[size++] = i; } int pop() { return stk[--size]; } }; stack s; // Пример s.push(5); s.push(10); s.push(2); cout
Задача 3: динамический стек class dynstack { int size; // Количество элементов int maxsize; // Макс. количество int* p; // Отведенная память public: dynstack() : size(0), maxsize(10) { p = new int[maxsize]; } ~dynstack() { delete [] p;// Многие забыли.. } void push(int val) { if (size == maxsize) { // Нет места? int* newp = new int[maxsize*2]; // Копируем for (int i=0; i
Классы (продолжение) Язык С++ - занятие 49
Объявление класса class abc; class klm { abc* p; … }; class abc { klm* q; … }; Язык С++ - занятие 4
Технические детали: конструкторы по умолчанию иногда создается автоматически Создается автоматически, если вообще нет конструкторов. class abc { … нет ни одного конструктора … }; Хотелось бы писать: abc x; abc a[10]; Автоматически добавляется: abc () {} И из-за этого бывают проблемы.. class abc { … нет конструкторов … }; abc x;// Все в порядке Перестанет работать, когда мы добавим любой конструктор Язык С++ - занятие 411
Наследование Язык С++ - занятие 412
Пример – время с секундами class time_with_sec : public time { int sec; public: time_with_sec(int h, int m, int s); void inc_sec(); void print(); }; time_with_sec::time_with_sec (int h, int m, int s): time(h, m), sec(s) {} void time_with_sec::inc_sec() { sec++; if ( sec == 60 ) { sec = 0; inc(); } void time_with_sec::print() { time::print(); cout
Замечания 1. public наследование (другие почти не встречаются) 2. Слова: базовый класс / производный класс 3. Можем использовать поля и методы базового класса, как будто они наши собственные 4. Можем доопределять поля и методы (sec, inc_sec) 5. конструктор базового класса вызывается в списке инициализации 6. time::print() – указываем, что нас интересует именно метод базового класса 7. Самое главное – можно переопределять методы 8. Переопределяемые методы надо определять, как виртуальные (практически всегда) Язык С++ - занятие 414
protected поля и методы Такие методы доступны из производных классов. Например, м.б. лучше в time : class time { protected: int hour, min;// Можно использовать в time // и в производных классах … Язык С++ - занятие 415
Виртуальные функции (!!!) Правило: Если вы собираетесь переопределить функцию в производном классе, то в базовом классе вы должны описать ее, как виртуальную. class time { virtual void print(); … Язык С++ - занятие 416
Разница между виртуальными и не виртуальными функциями. Динамическое связывание. time* p; if ( …какое-то условие… ) { p = new time(8, 50); } else { p = new time_with_sec (11, 30, 15); } // на что указывает p ?? // - неизвестно.. p->print();// Какой print // будет вызван? Если функция виртуальная, то будет вызываться «правильный» print: time::print() или time_with_sect::print() в зависимости от типа p Называется: динамическое связывание (dynamic binding) или позднее связывание (late binding) Язык С++ - занятие 417
Почему это важно. void my_print(time& p) { cout
Еще другими словами: как понимать слово virtual... Если нам дали класс, в котором есть виртуальная функция: class abc { virtual void f(); Это надо читать так: «… Функцию f вы можете переопределить и задать свой вариант…» Язык С++ - занятие 419
Как это все реализовано? Тут объяснялось, как обычно реализуются виртуальные функции (таблица виртуальных методов, vtable). Все рисовалось на доске, в слайдах этого нет… Язык С++ - занятие 420
Чисто виртуальные функции, абстрактные базовые классы Язык С++ - занятие 421
Пример: фигуры Рассмотрим набор классов для геометрических фигур: квадраты, ромбы, круги, треугольники и т.д. class shape { protected: int x, y; public: virtual void draw() = 0; shape(int x_, y_) : x(x_), y(y_) {} … еще методы (площадь, периметр и т.д.) … } ; Язык С++ - занятие 422
Чисто виртуальные функции В описании стоит =0; - функция называется чисто виртуальной (pure virtual). Это значит: Можно не задавать ее определения Ее обязательно надо переопределить в одном из производных классов Язык С++ - занятие 423
Абстрактные базовые классы Если в классе есть хотя бы одна чисто виртуальная функция: Такой класс называется абстрактным (abstract base class) Нельзя создавать объекты абстрактного класса shape s;// Ошибка: нельзя создать об ъ ект // абстрактного класса Все это относится и к производным классам, если в базовом классе была чисто виртуальная функция, и ее еще не определили Язык С++ - занятие 424
Если в документации написано virtual... = 0; class abc { virtual void f() = 0; Это надо читать так: «… Функцию f вы должны переопределить и задать свой вариант. …» Язык С++ - занятие 425
Сложные типы Язык С++ - занятие 426
Как определять сложные типы? a - массив из 10 укaзателей на int Массив из 10 указателей на int a a[10] *(a[10]) int *(a[10]); // Или int *a[10]; Язык С++ - занятие 427
Как читать сложные типы? int (*a)[10]; а *a*a (*a)[10] int (*a)[10]; a – это указатель на массив из 10 int Язык С++ - занятие 428
typedef Синтаксис: typedef описание переменной; typedef unsigned long ulong; typedef int* my_array[10]; my_array a; // тоже, что int* a[10]; Замечание - typedef не определяет новый тип – просто сокращенную запись для существующего типа void f(unsigned long i) { … } void f(ulong j) // Ошибка - {// у функций одинаковые …// параметры } Язык С++ - занятие 429
Зачем нужен typedef ? 1. Сокращенная запись typedef unsigned long ulong; 2. typedef int MY_INTEGER; Потом легче менять (encapsulation) 3. Технические причины: typedef int* pint; pint a[10]; p = new pint[20]; Язык С++ - занятие 430
Задачи на 17 марта Язык С++ - занятие 431
Задачи на 17 марта 1. a. Определить класс «ромб» (с диагоналями, параллельными осям координат). Для него определить конструктор и метод draw. (В методе draw вместо рисования можно просто печатать координаты отрезков). б. Определить какой-нибудь класс, производный от класса «ромб». 2. Написать абстрактный класс shape и производные от него классы rhomb и square. Для этих классов определить конструкторы и методы area (площадь) и perim (периметр). (Метод draw определять не надо). 3. Определить структуру (или класс) «односвязный список». а. Ввести число n и создать список из чисел n, n-1, n-2, … 3, 2, 1. б. Напечатать все числа в списке. (См. также документ про списки на сайте) Язык С++ - занятие 432