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

АФТИ ООП 2013-2014. Лекция II/4

АФТИ ООП 2013-2014. Лекция II/4

Oleg Dashevskii

March 10, 2014
Tweet

More Decks by Oleg Dashevskii

Other Decks in Education

Transcript

  1. ОПЕРАТОРЫ ИНКРЕМЕНТА И ДЕКРЕМЕНТА SomeValue& SomeValue::operator++() // prefix! {! ++data;!

    return *this;! }! ! SomeValue SomeValue::operator++(int unused) // postfix! {! SomeValue result = *this;! ++data;! return result;! }! SomeValue v;! ! ++v; // prefix! v++; // postfix
  2. // postfix! SomeValue SomeValue::operator++(int unused)! {! SomeValue result = *this;!

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

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

    to be enough for everyone!! T array[100];! public:! // ...! T &operator[](size_t idx) {! return array[idx];! }! ! const T &operator[](size_t idx) const {! return array[idx];! }! };
  5. 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;
  6. ОПЕРАТОР ВЫЗОВА ФУНКЦИИ • operator() должен быть членом класса, других

    ограничений нет. • Активно используется в STL для создания функторов. • std::unary_function • std::binary_function • …
  7. template <class _Arg, class _Result>! struct unary_function {! typedef _Arg

    argument_type;! typedef _Result result_type;! };! ! template <class _Arg1, class _Arg2, class _Result>! struct binary_function {! typedef _Arg1 first_argument_type;! typedef _Arg2 second_argument_type;! typedef _Result result_type;! };! ! template <class _Tp>! struct plus : public binary_function<_Tp, _Tp, _Tp> {! _Tp operator()(const _Tp& __x, const _Tp& __y) const {! return __x + __y;! }! };! ! template <class _Tp>! struct negate : public unary_function<_Tp, _Tp> {! _Tp operator()(const _Tp& __x) const {! return -__x;! }! };
  8. #include <iostream>! #include <functional>! #include <algorithm>! ! using namespace std;!

    ! int main () {! int numbers[] = {10, -20, -30, 40, -50};! int cx;! cx = count_if(numbers, numbers+5, bind2nd(less<int>(),0));! cout << "There are " << cx << " negative elements.\n";! return 0;! }!
  9. template <typename T>! class undeletable_pointer {! public:! undeletable_pointer(T *ptr) :

    base(ptr) {}! // ...! private:! void operator delete(void *);! T *base;! };! ! struct SomeObject {! typedef undeletable_pointer<SomeObject> undeletable_ptr;! ! undeletable_ptr operator&() { return this; }! };!
  10. class Err {};! ! class Giant {};! ! class Big

    {! public:! Big() { throw Err(); }! };! ! class MyClass {! Giant *giant;! Big *big;! public:! MyClass(): giant(new Giant()), big(new Big()) {}! ! ~MyClass() { delete giant; delete big; }! };! ! int main()! {! try {! MyClass myobject;! } catch (Err) {}! ! return 0;! }! К «умным» указателям
 (smart pointer) Решение: заменить указатели 
 объектами с объявленными 
 деструкторами
  11. template <typename T>! class SmartPtr {! T *ptr;! public:! SmartPtr(T

    *p) : ptr(p) {};! T& operator*() { return *ptr; }! T* operator->() { return ptr; }! ! ~SmartPtr() {! delete ptr;! }! };! Первое приближение
  12. template <typename T>! class SmartPtr {! T *ptr;! public:! explicit

    SmartPtr(T *p = 0) : ptr(p) {}! T& operator*() const { return *ptr; }! T* operator->() const { return ptr; }! ! SmartPtr(SmartPtr<T> &other) : ptr(other.release()) {}! ! SmartPtr operator=(SmartPtr<T>& other) {! if (this != &other)! reset(other.release());! return *this;! }! ! ~SmartPtr() { delete ptr; }! ! T *release() {! T *oldPtr = ptr;! ptr = 0;! return oldPtr;! }! ! void reset(T *newPtr) {! if (ptr != newPtr) {! delete ptr;! ptr = newPtr;! }! }! };
  13. ОПЕРАТОР ЗАПЯТАЯ • Позволяет делать интересные вещи, например: ! !

    • https://gist.github.com/be9/9459195 // Blitz++! Array<int,2> A(3,3);! ! A = 1, 0, 0,! 0, 1, 0,! 0, 0, 1;!
  14. ПРЕОБРАЗОВАНИЕ ТИПА class Y {! // ...! };! ! ostream

    &operator<<(ostream &os, const Y &y);! ! class X {! // ...! operator bool() const;! operator Y() const;! };! ! X x;! if (x) {! // ...! }! ! Y y(x);! cout << x;
  15. class Point2D {! int x;! int y;! public:! Point2D(int p,

    int q) : x(p), y(q) {}! friend class Point3D;! };! ! class Point3D {! int x;! int y;! int z;! public:! Point3D(int p, int q, int r) : x(p), y(q), z(r) {}! Point3D(const Point2D &point2D) :! x(point2D.x), y(point2D.y), z(0) {}! ! friend ostream& operator<<(ostream& os, const Point3D& point);! };! ! ostream& operator<<(ostream& os, const Point3D& point) {! os << "(" << point.x <<", " << point.y << ", " << point.z << ")";! return os;! }! ! int main() {! Point2D point2D(3, 4);! cout << point2D << endl;! return 0;! }!
  16. ПРАВИЛА • Если у класса объявлен конструктор с одним аргументом,

    компилятор может делать «преобразование типа» путем создания временного объекта. • Ключевое слово explicit запрещает компилятору преобразовывать типы.
  17. void f(const Y &);! ! class Y {! Y(const X

    &);! };! ! X x;! f(x);! ! /////////////////! ! class Array {! public:! Array(int size);! };! ! Array a('?'); void f(const Y &);! ! class Y {! explicit Y(const X &);! };! ! X x;! f(x); // error! ! /////////////////! ! class Array {! public:! explicit Array(int size);! };! ! Array a('?'); // error
  18. ОПЕРАТОРЫ, СВЯЗАННЫЕ 
 С ПАМЯТЬЮ • operator new • operator

    new[] • operator delete • operator delete[] • Требуют аккуратности и очень прямых рук, поэтому мы их рассматривать не будем :)
  19. ОПЕРАТОРЫ, КОТОРЫЕ НЕЛЬЗЯ ПЕРЕГРУЗИТЬ • ? : (тернарный) • .

    (доступ к члену класса) • .* (доступ к члену класса по указателю) • :: (namespace) • sizeof • typeid