320 likes | 471 Views
Д.з. на 3 марта. Задача 1: треугольный массив. int* a[10]; // Создаем.. for (int i = 0; i<10; i++) { a[i] = new int[i+1]; } // Заполняем for (int i = 0; i<10; i++) { for (int j = 0; j<=i; j++) { a[i][j] = (i == j); } }. // Печатаем for (int i = 0; i<10; i++) {
E N D
Д.з. на 3 марта Язык С++ - занятие 4
Задача 1: треугольный массив int* a[10]; // Создаем.. for (int i = 0; i<10; i++) { a[i] = new int[i+1]; } // Заполняем for (int i = 0; i<10; i++) { for (int j = 0; j<=i; j++) { a[i][j] = (i == j); } } // Печатаем for (int i = 0; i<10; i++) { for (int j = 0; j<=i; j++) { cout << a[i][j] << " "; } cout << "\n"; } 4.03.2008 Язык С++ - занятие 4 2
Задача 3: двоичный поиск • Делим массив пополам • Смотрим, в какой половине граница четных и нечетных • Повторяем то же с этой половиной • И так в цикле, пока длина куска массива >1 Язык С++ - занятие 4
Задача 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 << numEven(a, 10); 10.03.2009 Язык С++ - занятие 4 4
Д.з. на 10 марта 10.03.2009 Язык С++ - занятие 4 5
Задача 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 << a << b << c; 10.03.2009 Язык С++ - занятие 5 6
Задача 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 << s.pop(); // Печатает 2 int i = s.pop() – s .pop(); // В последней строчке // результат не определен! 10.03.2009 Язык С++ - занятие 5 7
Задача 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<size; i++) { newp[i] = p[i]; } maxsize *= 2; delete [] p; p = newp; // Переставляем } // указатель p[size++] = val; } int pop() { return p[--size]; } }; 10.03.2009 Язык С++ - занятие 4 8 8
Классы (продолжение) 10.03.2009 Язык С++ - занятие 4 9
Объявление класса class abc; class klm { abc* p; … }; class abc { klm* q; … }; Язык С++ - занятие 4
Технические детали: конструкторы по умолчанию иногда создается автоматически Создается автоматически, если вообще нет конструкторов. class abc { … нет ни одного конструктора …}; Хотелось бы писать:abc x;abc a[10]; Автоматически добавляется:abc (){} И из-за этого бывают проблемы.. class abc { … нет конструкторов …};abc x; // Все в порядке • Перестанет работать, когда мы добавим любой конструктор Язык С++ - занятие 4
Наследование Язык С++ - занятие 4
sec = 0; inc(); } } void time_with_sec::print() { time::print(); cout << "." << sec; } // использование time_with_sec time_with_sec ts(12, 30, 45); ts.inc(); ts.inc_sec(); ts.print(); Пример – время с секундами 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 ) { Язык С++ - занятие 4
Замечания • public наследование (другие почти не встречаются) • Слова: базовый класс / производный класс • Можем использовать поля и методы базового класса, как будто они наши собственные • Можем доопределять поля и методы (sec, inc_sec) • конструктор базового класса вызывается в списке инициализации • time::print() – указываем, что нас интересует именно метод базового класса • Самое главное – можно переопределять методы • Переопределяемые методы надо определять, как виртуальные (практически всегда) Язык С++ - занятие 4
protected поля и методы Такие методы доступны из производных классов. Например, м.б. лучше в time :class time {protected: int hour, min;// Можно использовать в time // и в производных классах … Язык С++ - занятие 4
Виртуальные функции (!!!) • Правило: Если вы собираетесь переопределить функцию в производном классе, то в базовом классе вы должны описать ее, как виртуальную. class time {virtual void print(); … Язык С++ - занятие 4
Разница между виртуальными и не виртуальными функциями. Динамическое связывание. 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) Язык С++ - занятие 4
Почему это важно. void my_print(time& p){ cout << "Московское время:"; p.print();} time t1(8, 50);time_with_sec t2(11, 30, 15); my_print(t1);my_print(t2); Будут вызваны разные print ! • Виртуальные функции позволяют писать код, который умеет работать с разными типами! Называется: полиморфизм Язык С++ - занятие 4
Еще другими словами: как понимать слово virtual... • Если нам дали класс, в котором есть виртуальная функция:class abc {virtual void f(); • Это надо читать так:«… Функцию f вы можете переопределить и задать свой вариант…» Язык С++ - занятие 4
Как это все реализовано? Тут объяснялось, как обычно реализуются виртуальные функции (таблица виртуальных методов, vtable). Все рисовалось на доске, в слайдах этого нет… 10.03.2009 Язык С++ - занятие 4 20
Чисто виртуальные функции, абстрактные базовые классы Язык С++ - занятие 4
Пример: фигуры Рассмотрим набор классов для геометрических фигур: квадраты, ромбы, круги, треугольники и т.д. class shape { protected: int x, y; public: virtual void draw() = 0; shape(int x_, y_) : x(x_), y(y_) {} … еще методы (площадь, периметр и т.д.) …}; Язык С++ - занятие 4
Чисто виртуальные функции • В описании стоит =0;- функция называется чисто виртуальной (pure virtual). Это значит: • Можно не задавать ее определения • Ее обязательно надопереопределить в одном из производных классов. Язык С++ - занятие 4
Абстрактные базовые классы • Если в классе есть хотя бы одна чисто виртуальная функция: • Такой класс называется абстрактным (abstract base class) • Нельзя создавать объекты абстрактного класса shape s; // Ошибка: нельзя создать объект // абстрактного класса • Все это относится и к производным классам, если в базовом классе была чисто виртуальная функция, и ее еще не определили. Язык С++ - занятие 4
Если в документации написано virtual... = 0; class abc {virtual void f() = 0; • Это надо читать так:«… Функцию f вы должны переопределить и задать свой вариант. …» Язык С++ - занятие 4
Сложные типы 10.03.2009 Язык С++ - занятие 4 26
Как определять сложные типы? a - массив из 10 укaзателей на int Массив из 10 указателей на int a a[10] *(a[10]) int *(a[10]);// Или int *a[10]; 10.03.2009 Язык С++ - занятие 4 27
Как читать сложные типы? int (*a)[10]; а *a (*a)[10] int (*a)[10]; a – это указатель на массив из 10 int 10.03.2009 Язык С++ - занятие 4 28
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) // Ошибка - {// у функций одинаковые …// параметры } 10.03.2009 Язык С++ - занятие 4 29
Зачем нужен typedef ? Сокращенная записьtypedef unsigned long ulong; typedef int MY_INTEGER; Потом легче менять (encapsulation) Технические причины: typedef int* pint; pint a[10]; p = new pint[20]; 10.03.2009 Язык С++ - занятие 4 30
Задачи на 17 марта Язык С++ - занятие 4
Задачи на 17 марта • a. Определить класс «ромб» (с диагоналями, параллельными осям координат). Для него определить конструктор и метод draw. (В методе draw вместо рисования можно просто печатать координаты отрезков).б. Определить какой-нибудь класс, производный от класса «ромб». • Написать абстрактный класс shape и производные от него классы rhomb и square. Для этих классов определить конструкторы и методы area (площадь) и perim (периметр). (Метод draw определять не надо). • Определить структуру (или класс) «односвязный список». а. Ввести число n и создать список из чисел n, n-1, n-2, … 3, 2, 1.б. Напечатать все числа в списке.(См. также документ про списки на сайте). Язык С++ - занятие 4