'

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

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





Слайд 0

Объектно-ориентированное программирование С++. Лекция 9 Карпов В.Э.


Слайд 1

ООП C++ 2 "Попинаем" C++ Диссертация Б. Страуструпа, программа на яз. Симула. Программа была написана очень быстро и легко. Скорость работы этой программы крайне мала (говорят, ее не хватало даже для того, чтобы насчитать необходимые данные к моменту защиты диссертации). => Желание создать свой язык, который бы совмещал в себе высокую скорость разработки (от Симулы) и высокую скорость выполнения (от С).


Слайд 2

ООП C++ 3 Цели нового языка Язык должен быть объектно-ориентированным. Язык должен быть эффективным. Язык должен быть таким, чтобы программисты на С могли легко на него перейти. Компилятор должен находить все возможные ошибки Технология создания первого компилятора C++: На языке C был написан препроцессор, преобразующий подмножество нового языка в обычный язык C. На подмножестве C++ и был разработан первый транслятор с C++ и затем «раскручен» в C-код, пригодный к компиляции в исполняемую программу. Целевой машиной для первого C++ транслятора была любая машина, способная выполнять C-программу (результатом трансляции был C-код).


Слайд 3

ООП C++ 4 Претензии к C++ "C++ мутирует чуть ли не каждый квартал, постепенно превращаясь в игрушку-трансформер, а сам автор C++ вынужден выпускать одну книжку за другой для толкования своего детища." "С внедрением языка C++ в коммерческую разработку резко упала надежность программного обеспечения." "Чрезмерная избыточность языка C++ привела к тому, что один и тот же алгоритм каждый программист кодирует по-своему и не самым оптимальным способом." "C++ - просто бескрайнее море перегруженных операторов."


Слайд 4

ООП C++ 5 Объекты "C++ - не "настоящий" объектный язык" Безуспешные попытки построения единой иерархии классов с общим базовым классом Object (идея Smalltalk). В C++ тщательно продуманные иерархии библиотек классов оказывались негибкими, а работа классов — неочевидной. Для того чтобы библиотеками классов можно было пользоваться, их приходилось поставлять в исходных текстах.


Слайд 5

ООП C++ 6 Шаблоны и объем кода Появление шаблонных классов поставило крест на этом направлении развития: Наследованием стали пользоваться только в тех случаях, когда требовалось порождение специализированной версии имеющегося класса. Библиотеки стали составляться из отдельных классов и небольших несвязанных друг с другом иерархий. => Стало снижаться повторное использование кода, т.к. в C++ невозможно полиморфное использование классов из независимых иерархий. Повсеместное применение шаблонов ведет к недопустимому росту объема скомпилированного кода (шаблоны реализуются методами макрогенерации).


Слайд 6

ООП C++ 7 Проблемы двоичной совместимости Один из тяжелейших недостатков C++, унаследованный им от синтаксиса С, состоит в доступности компилятору описания внутренней структуры всех использованных классов. => Изменение внутренней структуры представления какого-нибудь библиотечного класса приводит к необходимости перекомпиляции всех программ, где эта библиотека используется. => Это сильно ограничивает разработчиков библиотек в части их модернизации (выпуская новую версию, они должны сохранять двоичную совместимость с предыдущей). => C++ "в чистом виде" не пригоден для ведения больших проектов.


Слайд 7

ООП C++ 8 C++ по-прежнему ненадежен void main(void) { int len = 10; char *pSource = "abcd"; char c; int n = 10; switch (len % 8) { case 0: { do { c = *pSource++; case 7: c = *pSource++; case 1: c = *pSource++; } while (--n > 0); } } }


Слайд 8

ООП C++ 9 Непредсказуемость кода Проблема "скрытого кода" void f (const std::string& s); При вызове f ("Hello, world!") будет создан объект класса std::string, он передается функции, а потом уничтожается. Т.е. вполне корректный и правильный код несет в себе скрытые затраты на создание и уничтожение объекта. Старые "претензии" к ссылкам:. void func1 (A& a); void func2 (A a);


Слайд 9

ООП C++ 10 Библиотека STL Standard Template Library (STL, Степанов) - надстройка над C++. Задачи: Упростить работу с C++ Сделать ее комфортной.


Слайд 10

ООП C++ 11 Возможности STL классы string и wstring реализующих динамические строки (с однобайтовыми и двубайтовыми символами); класс complex реализующий комплексные числа; классы по локализации приложений; потоки ввода/вывода для файлов, консоли и строк; классы обработки исключений; итераторы - сходные по функциональности с указателями объекты, используемые для обработки элементов контейнерных типов; контейнерные классы - классы по управлению множеством элементов одного типа, как vector - динамический массив; list - список; queue,deque - очередь; stack - стек; map, multimap - отображения (ассоциативные массивы); set - множество; алгоритмы - шаблоны функций для обработки элементов массивов и контейнерных классов; различные вспомогательные классы функциональные объекты - классы для которых перегружена операция (), используется в алгоритмах; pair - класс реализующий пару значений, используемый с отображениями; auto_ptr - простой "умный" указатель.


Слайд 11

ООП C++ 12 Исключения Механизм исключений позволяет легко отследить различные ошибки в программе. Операторы: try - определяет блок, в котором необходимо отследить исключения. throw - вызывает исключение указанного типа. catch() - определяет блок обработки исключения указанного типа. Подобных блоков может быть несколько для каждого типа. Если же тип исключения не важен или нужно обработать исключения по умолчанию, то в качестве аргумента используется троеточие.


Слайд 12

ООП C++ 13 Пример #include <iostream> using namespace std; float divfunc(float a, float b) { if(b==0) throw 1; return a/b; } void main(void) { float a,b,c; cout<<"input a, b: "; cin>>a>>b; try { c=divfunc(a,b); // если b==0, то следующая строка не выполнится cout<<"c="<<c<<endl; } catch(...) { cout<<"exception"<<endl; } }


Слайд 13

ООП C++ 14 Атрибут throw В некоторых компиляторах можно явно указать, что функция или метод могут вызвать исключение (другие компиляторы могут просто игнорировать такую конструкцию, не сообщая об ошибке синтаксиса). void func1(int a) throw(...) {} void func1(int a) throw() {} void func3(int a) throw(int) { if(a>5) throw 2; }


Слайд 14

ООП C++ 15 STL исключения В STL определено несколько классов исключений. Например, в файле stdexcept объявлены стандартные исключения: invalid_argument - вызывается при передаче неправильного аргумента; length_error - вызывается при превышении размера данных; out_of_range - вызывается при выходе за допустимые границы; overflow_error - вызывается при переполнении. Эти и другие классы являются потомками класса exception. Через виртуальный метод what можно получить дополнительную информацию об исключении. class logic_error: public exception { public: logic_error (const string& what_arg): str_(what_arg) { ; } virtual ~logic_error (); virtual const char * what () { return str_.data(); } private: string str_; }; class invalid_argument: public logic_error { public: invalid_argument (const string& what_arg): logic_error(what_arg) {;} virtual ~invalid_argument (); };


Слайд 15

ООП C++ 16 Пример #include <iostream> #include <stdexcept> using namespace std; class Range { int r1,r2,pos; public: Range(int rr1,int rr2, int ppos) { r1=rr1; r2=rr2; pos=ppos; } void setPos(int ppos) { if(ppos<r1 ||ppos>r2) throw std::invalid_argument("setPos illegal argument"); pos=ppos; } }; void main(void) { Range r(10,20,12); try { r.setPos(25); } catch(exception &e) { cout<<e.what(); } catch(...) { cout<<"unknown exception"<<endl; } }


Слайд 16

ООП C++ 17 Класс auto_ptr Класс auto_ptr (простой "умный" указатель) имеет следующие ограничения: объектом может владеть только один указатель, объектом не может быть массив, нельзя использовать адресную арифметику. Единственное назначение этого класса - автоматизировать уничтожение выделенной ранее памяти. Данный класс используется, когда время существование выделенного объекта можно ограничить определенным блоком. Делая код более безопасным, данные классы не наносят ущерб размеру или скорости программы.


Слайд 17

ООП C++ 18 Пример #include <memory> // объявление шаблона класса auto_ptr #include <iostream> using namespace std; // Внутри функции мы выделяем память для объекта типа int // но не освобождаем ее явно оператором delete. // Это делается автоматически. void main(void) { auto_ptr<int> aptr(new int(20)); auto_ptr<int> aptr2; cout<<"*aptr="<<*aptr<<endl; aptr2=aptr; // теперь aptr не владеет никаким объектом cout<<"*aptr2="<<*aptr2<<endl; }


Слайд 18

ООП C++ 19 Итераторы библиотеки STL Итераторы - удобная обертка для указателей, а выполнены они как шаблоны классов. "Обычный" указатель тоже можно считать итератором (очень примитивным). Удобства итераторов: автоматическое отслеживание размера типа, на который указывает итератор, автоматизированные операции инкремента и декремента для перехода от элемента к элементу и т.д. 2 важных правила работы с итераторами: получения итераторов и отслеживания значения "за пределом". Метод begin() - возвращает итератор, указывающий на первый элемент данных Метод end() - возврат значения "за пределом" (past-the-end). Итераторы: основные и вспомогательные.


Слайд 19

ООП C++ 20 Фрагменты определений template <class _Tp, class _Alloc> class _Vector_base { public: ... _Vector_base(const _Alloc& __a) : _M_start(0), _M_finish(0), _M_end_of_storage(__a, 0) { } _Vector_base(size_t __n, const _Alloc& __a) : _M_start(0), _M_finish(0), _M_end_of_storage(__a, 0) { _M_start = _M_end_of_storage.allocate(__n); _M_finish = _M_start; _M_end_of_storage._M_data = _M_start + __n; } ~_Vector_base() { ... } protected: _Tp* _M_start; _Tp* _M_finish; ... }; template <class _Tp> class vector : public _Vector_base<_Tp, _Alloc> { ... typedef _Vector_base<_Tp, _Alloc> _Base; ... public: iterator begin() { return this->_M_start; } iterator end() { return this->_M_finish; } ... }


Слайд 20

ООП C++ 21 Итераторы ввода Наиболее простые из всех итераторов STL, и доступны они только для чтения. Оператор разыменовывания (*) для прочтения содержимого объекта, на который итератор указывает. Оператор (++) - перемещение от первого элемента, на который указывает итератор ввода, к следующему. Итераторы ввода возвращает только шаблонный класс istream_iterator.


Слайд 21

ООП C++ 22 Алгоритм for_each template <class InputIterator, class Function> Function for_each (InputIterator first, InputIterator last, Function f) { while (first != last) f(*first++); return f; } Или так: template <class InputIter, class Function> Function for_each(InputIter first, InputIter last, Function f) { for ( ; first != last; ++first) f(*first); return f; } #include <iostream> #include <algorithm> using namespace std; void printValue(int num) { cout << num << "\n"; } main(void) { int init[] = {1, 2, 3, 4, 5}; for_each(init, init + 5, printValue); }


Слайд 22

ООП C++ 23 Итераторы вывода #include <algorithm> #include <iostream> #include <vector> #include <iterator> using namespace std; main(void) { int init1[] = {1, 2, 3, 4, 5}; int init2[] = {6, 7, 8, 9, 10}; vector<int> v(10); merge(init1, init1 + 5, init2, init2 + 5, v.begin()); copy(v.begin(), v.end(), ostream_iterator<int>(cout, "\n")); }


Слайд 23

ООП C++ 24 Однонаправленные итераторы Если соединить итераторы ввода и вывода, то получится однонаправленный итератор (forward iterator), который может перемещаться по цепочке объектов в одном направлении. Для такого перемещения в итераторе определена операция инкремента (++). template <class ForwardIterator, class T> void replace(ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value) { while (first != last) { if (*first == old_value) *first = new_value; ++first; }} template <class ForwardIter, class Tp> void replace(ForwardIter first, ForwardIter last, const Tp& old_value, const Tp& new_value) { for ( ; first != last; ++first) if (*first == old_value) *first = new_value; }


Слайд 24

ООП C++ 25 Пример #include <algorithm> #include <iostream> #include <vector> #include <iterator> using namespace std; main(void) { int init[] = {1, 2, 3, 4, 5}; replace(init, init + 5, 0, 2); replace(init, init + 5, 1, 0); replace(init, init + 5, 2, 1); copy(init, init + 5, ostream_iterator<int>(cout, "\n")); }


Слайд 25

ООП C++ 26 Двунаправленные итераторы #include <algorithm> #include <iostream> #include <vector> #include <iterator> using namespace std; main(void) { int init[] = {1, 2, 3, 4, 5}; reverse(init, init + 5); copy(init, init + 5, ostream_iterator<int>(cout, "\n")); }


Слайд 26

ООП C++ 27 Итераторы произвольного доступа #include <algorithm> #include <iostream> #include <vector> using namespace std; void main(void) { const int init[] = {1, 2, 3, 4, 5}; vector<int> v(5); typedef vector<int>::iterator vectItr; vectItr itr; copy(init, init + 5, itr = v.begin()); cout << *( itr + 4 ) << endl; cout << *( itr += 3 ) << endl; cout << *( itr -= 1) << endl; cout << *( itr = itr - 1) << endl; cout << *( --itr ) << endl; for(int i = 0; i < (v.end() - v.begin()); i++) cout << itr[i] << " "; }


Слайд 27

ООП C++ 28 Итераторы потоков #include <algorithm> #include <iostream> #include <vector> #include <iterator> using namespace std; main(void) { istream_iterator<int> is(cin); ostream_iterator<int> os(cout, " - last entered value\n"); int input; while((input = *is) != 666) { *os++ = input; is++ ; } }


Слайд 28

ООП C++ 29 Итераторы вставки #include <algorithm> #include <iostream> #include <list> using namespace std; main(void) { int init[] = {0, 0}; int init1[] = {3, 2, 1}; int init2[] = {1, 2, 3}; int init3[] = {1, 1, 1}; list<int> l(2); copy(init, init + 2, l.begin()); copy(l.begin(), l.end(), ostream_iterator<int>(cout, " ")); cout << " - before front_inserter" << endl; copy(init1, init1 + 3, front_inserter(l)); copy(l.begin(), l.end(), ostream_iterator<int>(cout, " ")); cout << " - before back_inserter" << endl; copy(init2, init2 + 3, back_inserter(l)); copy(l.begin(), l.end(), ostream_iterator<int>(cout, " ")); cout << " - before inserter" << endl; list<int>::iterator& itr = l.begin(); advance(itr, 4); copy(init3, init3 + 3, inserter(l, itr)); copy(l.begin(), l.end(), ostream_iterator<int>(cout, " ")); }


×

HTML:





Ссылка: