Д.з. на 3 марта
DESCRIPTION
Д.з. на 3 марта. Задача 1: треугольный массив. int* a[10]; // Создаем.. for (int i = 0; iTRANSCRIPT
Д.з. на 3 марта
10.03.2009 Язык С++ - занятие 4 1
Задача 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
10.03.2009 Язык С++ - занятие 4 3
Задача 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(); // Печатает 2int 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 88
Классы (продолжение)
10.03.2009 Язык С++ - занятие 4 9
Объявление классаclass abc;
class klm {abc* p;…
};
class abc {klm* q;…
};
10.03.2009 10Язык С++ - занятие 4
Технические детали: конструкторы по умолчанию иногда создается автоматическиСоздается автоматически, если
вообще нет конструкторов.
class abc {… нет ни одного
конструктора …};
Хотелось бы писать:abc x;abc a[10];
Автоматически добавляется:
abc (){}
И из-за этого бывают проблемы..
class abc { … нет конструкторов …};
abc x; // Все в порядке
Перестанет работать, когда мы добавим любой конструктор
10.03.2009 Язык С++ - занятие 4 11
Наследование
10.03.2009 Язык С++ - занятие 4 12
Пример – время с секундами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 << "." << sec;}
// использование time_with_sectime_with_sec ts(12, 30, 45);ts.inc();ts.inc_sec();ts.print();
10.03.2009 Язык С++ - занятие 4 13
Замечания1. public наследование (другие почти не встречаются)2. Слова: базовый класс / производный класс3. Можем использовать поля и методы базового класса, как
будто они наши собственные 4. Можем доопределять поля и методы (sec, inc_sec)5. конструктор базового класса вызывается в списке
инициализации6. time::print() – указываем, что нас интересует именно метод
базового класса7. Самое главное – можно переопределять методы8. Переопределяемые методы надо определять, как виртуальные
(практически всегда)
10.03.2009 Язык С++ - занятие 4 14
protected поля и методыТакие методы доступны из производных классов. Например, м.б. лучше в time :
class time {protected: int hour, min; // Можно использовать в time
// и в производных классах …
10.03.2009 Язык С++ - занятие 4 15
Виртуальные функции (!!!) Правило:
Если вы собираетесь переопределить функцию в производном классе, то в базовом классе вы должны описать ее, как виртуальную.
class time {virtual void print();…
10.03.2009 Язык С++ - занятие 4 16
Разница между виртуальными и не виртуальными функциями. Динамическое связывание.
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)
10.03.2009 Язык С++ - занятие 4 17
Почему это важно. 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 ! Виртуальные функции позволяют писать код, который умеет
работать с разными типами!Называется: полиморфизм
10.03.2009 Язык С++ - занятие 4 18
Еще другими словами: как понимать слово virtual... Если нам дали класс, в котором есть
виртуальная функция:
class abc { virtual void f();
Это надо читать так:«… Функцию f вы можете переопределить и задать свой вариант…»
10.03.2009 Язык С++ - занятие 4 19
Как это все реализовано?Тут объяснялось, как обычно реализуются
виртуальные функции (таблица виртуальных методов, vtable).
Все рисовалось на доске, в слайдах этого нет…
10.03.2009 Язык С++ - занятие 4 20
Чисто виртуальные функции, абстрактные
базовые классы
10.03.2009 Язык С++ - занятие 4 21
Пример: фигурыРассмотрим набор классов для геометрических фигур: квадраты, ромбы, круги, треугольники и т.д.
class shape {
protected:int x, y;
public:virtual void draw()
= 0;shape(int x_, y_) :
x(x_), y(y_){}
… еще методы (площадь, периметр и т.д.) …};
10.03.2009 Язык С++ - занятие 4 22
Чисто виртуальные функции В описании стоит =0; - функция называется чисто
виртуальной (pure virtual). Это значит:
Можно не задавать ее определения
Ее обязательно надо переопределить в одном из производных классов.
10.03.2009 Язык С++ - занятие 4 23
Абстрактные базовые классы Если в классе есть хотя бы одна чисто виртуальная
функция:
Такой класс называется абстрактным (abstract base class)
Нельзя создавать объекты абстрактного класса
shape s; // Ошибка: нельзя создать объект // абстрактного класса
Все это относится и к производным классам, если в базовом классе была чисто виртуальная функция, и ее еще не определили.
10.03.2009 Язык С++ - занятие 4 24
Если в документации написано virtual ... = 0;
class abc {virtual void f() = 0;
Это надо читать так: «… Функцию f вы должны переопределить и задать свой вариант. …»
10.03.2009 Язык С++ - занятие 4 25
Сложные типы
10.03.2009 Язык С++ - занятие 4 26
Как определять сложные типы?
a - массив из 10 укaзателей на int
Массив из 10указателей на int
aa[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 ?1. Сокращенная запись
typedef unsigned long ulong;
2. typedef int MY_INTEGER;
Потом легче менять (encapsulation)
3. Технические причины:
typedef int* pint;pint a[10];
p = new pint[20];
10.03.2009 Язык С++ - занятие 4 30
Задачи на 17 марта
10.03.2009 Язык С++ - занятие 4 31
Задачи на 17 марта1. a. Определить класс «ромб» (с
диагоналями, параллельными осям координат). Для него определить конструктор и метод draw. (В методе draw вместо рисования можно просто печатать координаты отрезков).
б. Определить какой-нибудь класс, производный от класса «ромб».
2. Написать абстрактный класс shape и производные от него классы rhomb и square. Для этих классов определить конструкторы и методы area (площадь) и perim (периметр). (Метод draw определять не надо).
3. Определить структуру (или класс) «односвязный список». а. Ввести число n и создать список из чисел n, n-1, n-2, … 3, 2, 1.б. Напечатать все числа в списке.
(См. также документ про списки на сайте).
10.03.2009 Язык С++ - занятие 4 32