1 / 56

Еще раз про экзамен

Еще раз про экзамен. 22 мая – 10 :00 Сбор у баобаба. Для тех, кто придет позже – будет объявление на расписании 3 курса Вопрос 33 ( RTTI и typeid) вычеркивается Еще одна возможность сдать спец.курс будет в официальный день сдачи, 6 июня, в 10:00, сбор у баобаба. Задачи на 12 мая.

titus
Télécharger la présentation

Еще раз про экзамен

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Еще раз про экзамен • 22 мая – 10:00Сбор у баобаба. Для тех, кто придет позже – будет объявление на расписании 3 курса • Вопрос 33 (RTTI и typeid) вычеркивается • Еще одна возможность сдать спец.курс будет в официальный день сдачи, 6 июня, в 10:00, сбор у баобаба

  2. Задачи на 12 мая Язык С++ - 2

  3. Вариант с union union { double x; int a[2]; }; x = 2.71828; cout << a[0] << " " << a[1]; Вариант с преобразованием указателя x = 2.71828; int* p = (int*)&x; cout << a[0] << " " << a[1]; Или лучше так: int* p = reinterpret_cast<int*>(&x); (см. ниже) Задача: из каких int состоит double?

  4. Задачи на 19мая Язык С++ - 4

  5. ASSERT #ifdef DEBUG #define ASSERT(cond) \ if (!(cond)) \ cout << "Условие " #cond "не выполняется"; #else #define ASSERT(cond) #endif

  6. Cписок ошибок #define ERROR_TABLE map<int, string> errors; #define ERROR(num, message) errors[num] = message; … ERROR_TABLE ERROR(1, “Какая-то проблема“) ERROR(2, “Все плохо..“) ERROR(3, “У вас все неправильно“)

  7. Усложним немного задачу: Пусть я составил список ошибок, которые у меня будут выдаваться – с номерами и текстом ошибок. Но номера я записываю не как числа, а как символьные имена. И я бы хотел, чтобы с этими именами автоматически связывались числа 1, 2… по порядку. Т.е. я хочу, чтобы я записал список ошибок в каком-то таком виде: ERROR(someError, “Какая-то проблема“) ERROR(allBad, “Все плохо..“) ERROR(allWrong, “Все неправильно“) И автоматически генерировалось что-то такое: еnum{ someError, allBad, allWrong, }; map<int, string> errors; errors[someError] = “Какая-то проблема“; errors[allBad] = “Все плохо..“) errors[allWrong] = “Все неправильно“; Как это сделать? Это будет еще одно домашнее задание, самое последнее, просто для тех, кому это будет интересно.. Еще про задачу о списке ошибок

  8. Прием: разные определения для одного и того же макроса • Подсказка 1 – возможная схема --- errlist.h -------------------------------- ERROR(someError, “Какая-то проблема“) ERROR(allBad, “Все плохо..“) ERROR(allWrong, “Все неправильно“) -- основная программа ----------------- … … определения, чтобы сгенерировать enum #include "errlist.h" … определения, чтобы сгенерировать map #include "errlist.h" • Подсказка 2 – вам может потребоваться оператор препроцессора #undef#undef ABCСмысл: отменить определение ABC – нужно, если мы хотим его переопределить

  9. // Иерархия классов class CShape { public: virtual ~CShape() {} // Еще методы… }; class CSquare : public CShape {// Методы… }; class CCircle : public CShape {// Методы… }; class CRhomb : public CShape {// Методы… }; // Пример создания масива vector<CShape*> v; v.push_back(new CCircle()); v.push_back(new CSquare()); v.push_back(new CRhomb()); … // Считаем количество квадратов int cnt = 0; for (vector<CShape*>::iterator p = v.begin(); p != v.end(); p++) { if (typeid(**p) == typeid(CSquare)) cnt++; } Задача:Сколько квадратов?

  10. Замечание про RTTI

  11. Хочется использовать typeid? Скорее всего, надо ввести виртуальную функцию. (smell…) if (typeid(*p) == typeid(CCircle) cout << "Это круг"; else if (typeid(*p) == typeid(CSquare) cout << "Это квадрат"; else if (typeid(*p) == typeid(CTriang) cout << "Это треугольник";  cout << "Это" << p->name(); Когда все-таки имеет смысл использовать? Если мы не можем добавить виртуальную функцию в базовый класс.(Например, классы, производные от CView) Почему плохо использовать RTTI? Когда это все-таки имеет смысл?

  12. class my_comparator { int m; // 10^n public: my_comparator(int n) { // Calculate 10^n m = 1; for (int i = 0; i < n; i++) m *= 10; } bool operator() (int i, int j) { return i % m < j % m; } }; my_comparator cmp(n); sort(v.begin(), v.end(),cmp); или sort(v.begin(), v.end(),my_comparator(n)); Сортировка по последним n цифрам (с помощью функтора)

  13. Снова сумма положительных элементов Так мы написали.. template <class T> typename T::value_type sumpos(T b, T e) { typename T::value_type sum; for (T p = b; p!=e; p++) { if (*p > 0) { sum += *p; } } return sum; } • Просьба заказчика – пусть тип результата всегда int или double • T.e. требуется по одному типу найти другой по правилу: • float, double  double • Все остальное  int • Легко сказать – как это реализовать? • trait ! Язык С++ 13

  14. Cумма положительных элементов – новое решение template <class T> struct sum_trait { typedef int sum_type; }; template <> struct sum_trait<float> { typedef double sum_type; }; template <> struct sum_trait<double> { typedef double sum_type; }; #define SUM_TYPE \ typename sum_trait \ <typename T::value_type>:: \ sum_type template <class T> SUM_TYPE sumpos(T b, T e) { SUM_TYPE sum = 0; … дальше без изменений … } Язык С++ 14

  15. casts(static_cast, dynamic_cast и т.д.)

  16. Вместо существующего оператора преобразования рекомендуется выбрать один из 3 способов. static_cast Мы создаем объект, устроенный внутри по другому, но с тем же смыслом (примерно…) Т.е. “другие биты, тот же смысл…” T.e. раньше писали: int i = (int)x; complex x = (complex)x; Теперь рекомендуется писать: int i = static_cast<int>(x); reinterpret_cast double* px = &x;char* p = (char*) px; Те же биты, другой смысл… Объект тот же, но мы его интерпретируем по другому. Только в 3 случаях: указатель  указатель указатель  целое целое  указатель Т.е. рекомендуется писать: char* p = reinterpret_cast<char*>(px); Оказывается, преобразования бывают 4 видов

  17. const_cast Пусть у нас есть const int* p;Но мы точно знаем, что это не константа (просто неправильно описан параметр и т.д.). И очень надо ее поменять. int* p1 = (int*)p; *p = 55; Т.е. смысл тот же, биты те же. Только задаем или убираем спецификации const Т.е. рекомендуется писать: int* p1 = const_cast<int*>(p); const_cast

  18. shape* p; Пусть мы точно знаем, что p указывает на square square* p1 = (square*)p; p1->… делаем что-то специальное для квадрата (Это называется downcasting) Вообще-то можно проверить, действительно ли это квадрат.. По таблице вирт.функций Только если есть хотя бы одна вирт. функция Должна быть включена опция “Enable Runtime Type Info” Можно написать так: square* p1 = dynamic_cast<square*>(p); if (p1 == 0) cout << "Ошибка!"; dynamic_cast

  19. Тоже для ссылок: shape& sh; square& p1 = dynamic_cast<square&>(sh); Если не то – исключение (bad_cast) Заключение: Все виды cast лучше применять пореже Но, если вы действительно понимаете, зачем это вам надо – ОК, ничего страшного. dynamic_cast - продолжение

  20. Namespace Язык С++ 20

  21. Зачем нужны namespace? Проблема: Пусть есть две библиотеки классов: Библиотека ABCLIB. класс stack … Библиотека KLMLIB. класс stack #include <abclib.h> #include <klmlib.h> stack st; // Ошибка! Решение: В библиотеке ABCLIB: namespace abc {…class stack { … … } То же в KLMLIB: namespace klm {… class stack … } Теперь abc::stack и klm::stack Язык С++ 21

  22. Как обращаться к именам из namespace? Полное имя: abc::stack klm::stack using объявление using abc::stack; stack  abc::stack using директива using namespace abc; stack  пытается найти в abc Замечания: и using объявление и using директива действуют до конца блока. Совет: в h файлах – только полное имя Язык С++ 22

  23. Еще возможности Инкрементальное определение namespace abc { … определения …}… что-то вне namespace … namespace abc { … еще определения …} Глобальное пространство имен::f() – глобальная функция using ::f; M.б. вложенные abc::klm Язык С++ 23

  24. Еще возможности - 2 Безымянные (анонимные) namespace namespace { int v; …} Генерируется уникальное имя + using директива namespace <уник.имя> { int v; …} using namespace <уник.имя>; Означает: Переменную v можно использовать только от того места, где она определена, и до конца файла - примерно то же, что static Язык С++ 24

  25. Что мы не прошли… Язык С++ - 25

  26. Множественное наследование Язык С++ - 26

  27. class Car {// Автомобиль … }; class Ship {// Корабль … }; class Amphibia : public Car, public Ship { … }; В реальности с множественным наследованием обычно получается довольно сложно… Множественное наследование - 1

  28. Множественное наследование - 2 Надо ли использовать? Pазные точки зрения… • Да Например, ATL • Нет Например, MFC • Да, но только для интерфейсов (абстрактныe классов, вообще без кода, только с чисто виртуальными функциями) • (Так в Java, например)

  29. А / \ B1 B2 – наследники A \ / C – наследник B1, B2 diamond problem ромбовидная диаграмма Проблема: class A { protected: int x; void f(); }; Сколько в классе C экземпляров поля x? Хорошо бы один… (например, поле "руль" или "мотор" для амфибии) Vehicle (средство передвижения) поля "руль", "мотор" / \ Car Ship \ / Amphibia Diamond problem (ромбовидная диаграмма)

  30. Виртуальные базовые классы class A { … } class B1 : public virtual A { … }; class B2 : public virtual A { … }; class C : public B1, public B2 { … }; • Теперь x будет в C один раз • Класс А называется "виртуальный базовый класс"

  31. private и protected наследование Язык С++ - 31

  32. Класс group - студенческая группа. Представляется, как вектор из объектов класса student class group { vector<student> vect; public: void add(const student& s) void print() const; … }; void group::add(const student& s) { vect.push_back(st); } void group:: print() const { … for (p = vect.begin(); p != vecn.end(); p++) … } Пример

  33. Можно написать короче class group : vector<student> { public: void add(const student& s) void print() const; … }; void group::add(const student& s) { push_back(st); } void group:: print() const { … for (p = begin(); p != end(); … } Public наследование было бы неправильно! private неследование – унаследованные меиоды становятся private Т.е. снаружи наследование не видно… То же с private наследованием

  34. protected наследование • Примерно аналогично • Встречается еще реже

  35. Разные полезные вещи Язык С++ - 35

  36. atoi, itoa, atof, _fcvt и т.д. строковые потоки ostringstream sout; sout << i << " " << x; string s = sout.str(); И аналогично istringstream. Форматный ввод/вывод в т.ч. в строку. char s[20]; sprinf(s, "%10.3lf", x); Форматный вывод в MFC CString s; s.Format("%10.3lf", x); Преобразования строка  число

  37. Функции с переменным числом аргументов • #include <stdarg.h> va_start, va_arg, va_end int mysum(int n, …) Вызов: cout << mysum(2, n, k); cout << mysum(4, i, j, k, l); • Не рекомендуется использовать: Нет проверки параметров компилятором: mysum(2, i, j, k) mysum(2, 3.14, "abc") • Но иногда удобно

  38. & - побитовое "И" | - побитовое "ИЛИ" ^ - побитовое «исключающее ИЛИ» ~ - инвертировать виты << - сдвиг влево << - сдвиг влево Побитовые операциидля целых чисел

  39. Еще возможности для работы с битами • Битовые поля class { int a:3; int b:4; int c:1; }; • vector<bool> • bitset<n> bitset<100> b; b[i] = true; if ( b[i] ) …

  40. Полезные вещи в стандартной библиотеке и в boost Язык С++ - 40

  41. Указатели со счетчиком ссылок #include <memory> using namespace std::tr1; { shared_ptr<int> p(new int(56)); … { shared_ptr<int> p1 = p; … // Два указателя на 56 }// Теперь только один … } // Теперь нет указателей // Память освобождается shared_ptr

  42. Если не хотите думать о том, когда освобождать память class abc { shared_ptr<int> p; public: abc() : p(new int(56)) { } // В деструкторе писать // ничего не надо }; Для управления разделяемыми объектами shared_ptr

  43. Алгоритмы, параметры у которых - функции (или функторы) • find_if bool isPos(int i){ return i > 0;} find_if(v.begin(), v.end(), isPos); • Много такого типа • remove_if • transform • for_each • … и т.д. • Лично я почти никогда не использую…

  44. Итераторы вставки, итераторы потоков copy(v.begin(), v.end(), v1.begin()); • С помощью copy можно дописать в конец copy(v.begin(), v.end(), back_inserter(v1)); • С помощью copy можно записать в файл #include <iterator>… ostream_iterator<int> out_it(cout, “ “); copy(v.begin(), v.end(), out_it);

  45. Еще в boost • boost:: hash_map, hash_set • В C++ 0x – unordered_map, unordered_set • Вообще очень много чего (regex, graphs)

  46. C++0x Язык С++ - 46

  47. Только некоторые из новых возможностей: Инициализация контейнеров списком инициализации: vector<int> v = {3, 7, 11 }; Цикл по контейнеру:vector<int> v;for (x: v) { … Вывод типа (type inference) auto i = 3; auto x = 3.14; auto n = abc(x, y); for (auto p = v.begin(); p != v.end(); p++) C++ 0x – новый стандарт языка

  48. Функция, параметр которой – функция Пишем в параметре прямо код функции find_if(v.begin(), v.end(), [] (int x) { return x > 0; } ); sort(v.begin(), b.end(), [] (int x, int y) { return x % 10 < y % 10; } ); void f(vector<int> v, int n) { int m = 1; for (int i = 0; i < n; i++) m *= 10; sort(v.begin(), b.end(), [] (int x, int y) { return x % m < y % m; } ); } lambdas

  49. template <class T> T max(T x, T y) { return y < x ? x : y; }  template <Comparable T> T max(T x, T y) { return y < x ? x : y; } concept Comparable<typename T> { bool operator<(T x, T y); }; Более понятные сообщения об ошибках: complex c1, c2; max(c1, c2); "Error: complex is not Comparable" Обнаружение ошибок еще в шаблоне: template <Comparable T> T max(T x, T y) { … max = x; … "operator = not in Comparable" Concepts

  50. А вот что я сказал бы, если бы еще было время… Язык С++ - 50

More Related