Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Лекция 4. «Чёрные ящики» (ч. 2)

Лекция 4. «Чёрные ящики» (ч. 2)

ООП АФТИ НГУ 2015-2016. 2-й семестр

Oleg Dashevskii

February 29, 2016
Tweet

More Decks by Oleg Dashevskii

Other Decks in Education

Transcript

  1. ИНИЦИАЛИЗАЦИЯ
 C++11 STYLE X a1 {v}; // новое в C++11

    X a2 = {v}; // было ещё в C X a3 = v; // было ещё в C X a4(v); // «старый» C++
  2. ПРЕИМУЩЕСТВА {} • Нет «обрезания» типов. char можно присвоить int,

    но не наоборот. Аналогично с double и float. • Нет преобразования между целочисленными типами и типами с плавающей точкой.
  3. void f(double val, int val2) { int x2 = val;

    // если val==7.9, x2 <- 7 char c2 = val2; // если val2==1025, c2 <- 1 int x3 {val}; // ОШИБКА char c3 {val2}; // ОШИБКА char c4 {24}; // OK. 24 входит в char char c5 {264}; // ОШИБКА. 264 не входит в 8-битный char int x4 {2.0}; // ОШИБКА. int и double. // ... }
  4. int x4 {}; // 0 double d4 {}; // 0.0

    char *p {}; // nullptr vector<int> v4{}; // пустой вектор string s4 {}; // пустая строка char buf[1024] {}; // все символы 0 {} — значение по умолчанию
  5. struct Work { string author; string name; int year; };

    // Инициализация почленно Work s9 { "Beethoven", "Symphony No. 9 in D minor, Op. 125; Choral", 1824 }; // Конструктор копирования по умолчанию Work currently_playing { s9 }; Work none {}; // аналог: { {}, {}, {} } или { "", "", 0 } Инициализация
 объектов классов без конструкторов
  6. struct X { X(int); }; X x0; // ОШИБКА. Нет

    инициализации X x1 {}; // ОШИБКА. Пустая инициализация X x2 {2}; // ОК X x3 {"two"}; // ОШИБКА. Не тот тип. X x4 {1,2}; // ОШИБКА. Неверное количество X x5 {x4}; // OK. Конструктор копирования по умолч. Инициализация с конструктором
  7. struct S1 { int a, b; }; struct S2 {

    int a, b; S2(int aa = 0, int bb = 0) : a(aa), b(bb) {} }; S1 x11(1,2); // ОШИБКА. Нет конструктора S1 x12 {1,2}; // OK. Почленная инициализация S1 x13(1); // ОШИБКА. Нет конструктора S1 x14 {1}; // OK. x14.b <- 0 S2 x21(1,2); // ОК. Конструктор S2 x22 {1,2}; // ОК. Конструктор S2 x23(1); // OK. Конструктор с арг. по умолч. S2 x24 {1}; // OK. Конструктор с арг. по умолч.
  8. vector<double> v { 1, 2, 3.456, 99.99 }; list<pair<string,string>> languages

    { { "Nygaard", "Simula" }, { "Richards", "BCPL" }, { "Ritchie", "C"} }; map<vector<string>,vector<int>> years { { { "Maurice", "Vincent", "Wilkes" }, { 1913, 1945, 1951, 1967, 2000 } }, { { "Martin", "Richards"}, { 1982, 2003, 2007 } }, { { "David", "John", "Wheeler"}, { 1927, 1947, 1951, 2004 } } }; // НО КАК?!! Произвольное количество
 аргументов конструктора
  9. #include <initializer_list> #include <iostream> void f(std::initializer_list<int> list) { std::cout <<

    "Size = " << list.size() << std::endl; for (int x: list) std::cout << x << std::endl; } f({1, 2}); f({23, 345, 4567, 56789}); f({}); // Пустой список std::initializer_list<T>
  10. • Если можно вызвать конструктор по умолчанию или конструктор со

    списком, используется первый. • Если можно вызвать конструктор со списком или «обычный» конструктор, также используется первый. struct X { X(initializer_list<int>); X(); X(int); }; X x0 {}; // X() X x1 {1}; // X(initializer_list<int>)
  11. vector<int> v1 {1}; // Вектор из одного элемента: 1 vector<int>

    v2 {1,2}; // Вектор из двух элементов: 1,2 vector<int> v3(1); // Вектор из одного элемента: 0 (по умолч.) vector<int> v4(1,2); // Один элемент со значением 2 Разница между () и {}
  12. • Можно перегрузить поведение почти всех операторов, существующих в языке.

    • Нельзя создать новые операторы. • Нельзя повлиять на приоритет, арность или ассоциативность операторов.
  13. A a; SomeType b; // a + b class A

    { // ... return_type operator+(SomeType b); }; // b + a ? Оператор-член класса
  14. Оператор-глобальная функция class A { // ... friend return_type operator+(const

    A &, SomeType); friend return_type operator+(SomeType, const A &); }; inline return_type operator+(const A &a, SomeType b) { // ... } inline return_type operator+(SomeType b, const A &a) { // ... }
  15. АРИФМЕТИКА • + - * / % • Можно использовать

    оба варианта функций. • operator- бывает двух видов!
  16. ПОБИТОВЫЕ ОПЕРАЦИИ • ^ | & ~ << >> •

    Приоритет ниже, чем у арифметики:
 a ^ n + b воспримется как a ^ (n + b). • Можно использовать оба варианта функций. • << и >> используются стандартной библиотекой для ввода/вывода.
  17. ostream& operator<<(ostream& out, const Vector2D& vec) { // вывод out

    << "(" << vec.x() << ", " << vec.y() << ")"; return out; } istream& operator>>(istream& in, Vector2D& vec) { // ввод double x, y; // пропускаем открывающую скобку in.ignore(1); // читаем x in >> x; vec.set_x(x); // пропускаем разделитель in.ignore(2); // читаем y in >> y; vec.set_y(y); // пропускаем закрывающую скобку in.ignore(1); return in; }
  18. ОПЕРАТОР ПРИСВАИВАНИЯ • Только метод класса! • Существует реализация по

    умолчанию: копирование всех полей. • Если в классе присутствуют указатели, реализация по умолчанию приносит проблемы (см. предыдущая лекция).
  19. ОПЕРАТОРЫ СРАВНЕНИЯ • == != < <= > >= •

    Можно использовать оба варианта функций. • Чтобы не мучаться: • #include <utility> • using namespace std::rel_ops; • Определить operator== и operator< • Остальные операторы обеспечит STL
  20. ЛОГИЧЕСКИЕ ОПЕРАТОРЫ • ! && || • При задании operator&&

    теряется свойство «короткого замыкания».
  21. bool Function1() { return false; } bool Function2(); Function1() &&

    Function2(); ////////////////////////////////// MyBool Function3() { return MyBool::FALSE; } MyBool Function4(); bool operator&&(MyBool const &, MyBool const &); Function3() && Function4(); Function2() не будет вызвана, а Function4() – будет!
  22. ПРИСВОЕНИЕ- МОДИФИКАЦИЯ • += -= *= /= %= &= |=

    ^= <<= >>= • Метод класса! • operator+= не генерируется автоматически из operator= и operator+. • Нужно возвращать *this.
  23. ОПЕРАТОРЫ ИНКРЕМЕНТА И ДЕКРЕМЕНТА SomeValue& SomeValue::operator++() // префиксный { ++data;

    return *this; } SomeValue SomeValue::operator++(int unused) // постфиксный { SomeValue result = *this; ++data; return result; } SomeValue v; ++v; // префиксный ++ v++; // постфиксный ++
  24. // постфиксный SomeValue SomeValue::operator++(int unused) { SomeValue result = *this;

    ++(*this); // вызов SomeValue::operator++() return result; } Реализация постфиксного оператора 
 через префиксный
  25. • Должен быть членом класса. • Допустим один аргумент, зато

    любого типа. • Обычно переопределяется две версии: c const и без. ОПЕРАТОР ИНДЕКСА
  26. template <typename T> class StupidVector { // 100 элементов должно

    хватить всем! T array[100]; public: // ... T &operator[](size_t idx) { return array[idx]; } const T &operator[](size_t idx) const { return array[idx]; } };
  27. template <typename T> class Matrix; template <typename T> class MatrixColumn

    { public: MatrixColumn(Matrix *m, size_t r) : matrix(m), row(r) {} T &operator[](int col) { return matrix->element(row, col); } Matrix *matrix; size_t row; }; template <typename T> class Matrix { public: Matrix(int rows, int cols); // ... T &element(int row, int col); MatrixColumn<T> operator[](int row) { return MatrixColumn<T>(this, row); } }; Matrix<double> mat(3, 3); mat[2][2] = 10;