'

С++, ООП

Понравилась презентация – покажи это...





Слайд 0

С++, ООП Семинар 2 Рябова Анна Сергеевна ryabova.anna@gmail.com


Слайд 1

Задание 2 Реализовать шаблон класса для хранения динамического контейнера – очереди (FIFO) / стека(LIFO) / дека(двунаправленной очереди) элементов типа T template< class T > class Deque { … public: push_back(const T& Element) //Add element at the end push_front(const T& Element) //Insert element at beginning pop_back() //Delete last element pop_front() //Delete first element … }; Необходимо реализовать: на тройку: Операцию вставки (push, pop) в начало (стек, дек) или конец (дек, очередь) контейнера Операцию удаления из начала (стек, очередь, дек) или из конца(дек) Деструктор, освобождающий всю выделенную память ! Программу, демонстрирующую все вышеперечисленное на четверку Операцию объединения с контейнером того же типа Deque& addAll(const Deque& additional) Запрет использования конструктора копирования и оператора присваивания Программу, демонстрирующую эти возможности на пятерку Класс-итератор, перебирающий элементы контейнера при вызове ++, для которого определены операторы * и -> Программу, демонстрирующую работу итератора


Слайд 2

Шаблоны (templates) Перегрузка функций int max(int x, int y) { return x>y ? x : y ; } double max(double x, double y) { return x>y ? x : y ; } Одинаковая реализация, отличие лишь в типе аргументов Используем шаблон template<typename T> T max(T x, T y) { return x>y ? x : y; } Ключевое слово typename или class template <class T> ... //всегда будут использоваться классы template <typename T> ... //могут появиться типы int, char Если в программе появится вызов max() c двумя аргументами одного типа, то транслятор создаст для него по шаблону соответсвующую функцию (если он это не сделал раньше). max('c','d'); // instantiate max(char,char) max(1.0,2.0); // instantiate max(double,double) max('c','d'); // max(char,char) already exists


Слайд 3

Шаблоны (templates) Похоже на макроподстановки, но текстовая замена формального параметра шаблона на реальный тип происходит не в месте, где max() используется, а в теле автоматически созданной по заданному образцу функции. Шаблону можно указать несколько параметров-типов. template< typename T1, typename T2> int maxsize(T1 a, T2 b) { int size_a = sizeof(a); int size_b = sizeof(b); return size_a>size_b ? size_a : size_b; }


Слайд 4

Шаблоны (templates): подводные камни Транслятор создает по шаблону тела функций, точно соответсвующие сигнатуре вызова. Можно было обойтись одной функцией с сигнатурой, совместимой сразу с несколькими вызовами. Программа "распухает" - код автоматически сгенерированных функций занимает необоснованно много места в памяти. Текстовая замена формального типа на фактический в теле шаблона порой приводит к весьма причудливым конструкциям, которые могут давать ошибки при трансляции, или работать совсем не так, как замышлялось разработчиком шаблона. Старые компиляторы могут плохо поддерживать шаблоны


Слайд 5

Шаблоны классов template <typename T> class Vector { private: T arr[2]; public: Vector(T a, T b) { arr[0] = a; arr[1] = b; } T operator[](int index) const { if (index < 0 || index >= 2) throw "error"; return arr[index]; } }; Vector<int> v1(1, 2); Vector<double> v1(1.5, 2.2);


Слайд 6

Исключения (exceptions) С++-механизм для обработки ошибок Когда какая-нибудь функция обнаруживает ошибку, она сообщает об этом вызывающему коду, посылая исключение. unsigned factorial(unsigned val) { if (val > 22) throw "Argument too large"; return (val == 0 ? 1 : val*factorial(val-1)); } Ключевое слово throw + объект, который содержит информацию об ошибке (строка, переменная, структура, класс) объект несет двоякую информацию - тип исключения (const char*, текстовая строка), и описание конкретного случая (само содержимое этой строки). Оператор throw приводит к немедленному прекращению работы функции.


Слайд 7

exceptions: 1 вариант обработки 1. Никаких проверок в вызывающем коде не делается: main() { unsigned result; result = factorial(25); cout << result << endl; cout << "Goodbye" << endl; } Исключение, дойдя до функции main(), приведет к аварийному завершению программы unsigned factorial(unsigned val) { if (val > 22) throw "Argument too large"; return (val == 0 ? 1 : val*factorial(val-1)); }


Слайд 8

exceptions: 2 вариант обработки 2. Вызывающий код обрабатывает исключения код, который может генерировать исключения, обертывается в try-блок и назначая обработчик для нужного типа исключения с помощью catch-блока: main() { unsigned result; try { result = factorial(25); cout << result << endl; } catch (const char *msg) { cerr << " Factorial raised exception " << msg << endl; } cout << "Goodbye" << endl; } unsigned factorial(unsigned val) { if (val > 22) throw "Argument too large"; return (val == 0 ? 1 : val*factorial(val-1)); }


Слайд 9

exceptions: 2 вариант обработки Если исключения не возникает, то catch-блок не получает управления. Так что после вызова factorial() печатается результат и сразу после этого сообщение Goodbye. Если factorial() взводит исключение, то остальные операторы блока try не выполняются (в примере не печатается результат), и просматриваются catch-блоки, относящиеся к данному блоку try. Если удается отыскать подходящий по типу исключения, то его код и выполняется, причем в параметр "шапки" блока засылается тот объект, который пришел с исключением. Мы в нашем примере получаем строку с описанием ошибки в параметре msg блока catch, которую и печатаем. Если подходящего блока catch нет, конструкция try-catch не перехватывает исключение и реализуется первый сценарий. … try { result = factorial(25); cout << result << endl; } catch (const char *msg) { cerr << " Factorial raised exception “ << msg << endl; } cout << "Goodbye" << endl; …


Слайд 10

Исключения (exceptions) catch-блоков может быть несколько, каждый ловит свой тип исключений. При генерации исключения программа будет просматривать их один за другим, в том порядке, как они написаны, и выполнит код первого же подходящего по типу catch-блока: try { ... } catch (const char *msg) { cerr << "const char * exception handled" << endl; } catch (int error_number) { cerr << "int exception handled" << endl; } catch(...) { cerr << "Handler for any type of exception called" << endl; } catch(…) перехватывает исключения любого типа. Если поставить его первым, все остальные catch-блоки никогда не вызовутся. Что именно принято делать в блоках catch? подправить какие-то параметры и снова попытаться выполнить блок try вывести сообщение об ошибке вызвать exit(), чтобы программа завершилась не аварийно


Слайд 11

Пример программы #include <iostream> using namespace std; class ZeroDenominatorException {}; class TooLargeNumeratorException { public: int value; TooLargeNumeratorException(int value) { this->value = value; } }; double calculateFraction(int num, int denom) { if(num > 50) throw TooLargeNumeratorException(num); if(denom == 0) throw ZeroDenominatorException(); return (double)num/denom; } int main(void) { int num, denom; cout << "Enter numerator:"; cin >>num; cout << "Enter denominator:"; cin >> denom; try { double result = calculateFraction(num, denom); cout << "Result is " << result << endl; } сatch(ZeroDenominatorException) { cout << "Denuminator can not be 0" << endl; } catch(TooLargeNumeratorException e) { cout << "Too large numerator " << e.value; } catch(...) { cout << "Something elese went wrong"; } return 0; }


×

HTML:





Ссылка: