06 pointers to class members
TRANSCRIPT
Бублик Володимир Васильович
Програмування - 2
Лекція 6. Об'єктне програмування.
Типізація об'єктів
Лекції для студентів 2 курсу
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 2
Повторення
Тип функції (оператора) визначається її (його) сигнатурою
Приклад. Операція додавання комплексних чисел
• const Complex operator+• (const Complex &, const Complex &);
Або на два конструктори більше• const Complex operator+(Complex, Complex);Але не• Complex operator+(Complex, Complex);
Complex(1,1)+Complex(3,2) = Complex(-1,-1);
Complex(1,1)+Complex(3,2) = 0;
(Complex(1,1)+Complex(3,2)).re()=0;
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 3
Указники функцій
Використовуються для того, щоб передавати функції параметрами
• // Визначення указника функції• const Complex (*ptr_to_op)• (const Complex &, const Complex &) = operator+;
• // Визначення сталого указника функції• const Complex (* const const_ptr_to_op)• (const Complex &, const Complex &) = operator+;
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 4
Типи указників
• // Тип указника PFR• // (Pointer to Function with Referenced parameters)• typedef const Complex (*PFR)• (const Complex &, const Complex &);
• // Тип указника CPFR• // (Constant Pointer to Function …) • typedef const Complex (* const CPFR)• (const Complex &, const Complex &);
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 5
Визначення указників
• // Визначення указника типу PFR• // (Pointer to Function with Referenced parameters)• PFR pf = operator+;
• // Визначення сталого указника типу СPFR• // (Constant Pointer to Function with Referenced …)• CPFR addition = operator+;
Питання. Для чого потрібні сталі указники функцій?Відповідь. Для правильної передачі функціональних
параметрів
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 6
Типізація методів
• // Метод додавання• const Complex Complex::operator+• (const Complex&) const;
Тепер попереднє визначення указника не пройде
• const Complex (*ptr_to_op)• (const Complex &, const Complex &) = operator+;
Метод знає свій об'єкт this, а утиліта не знає
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 7
Тип указника методу
• // Тип указника CPMFR• // (Constant Pointer to member Function • // with a Referenced parameter)• typedef const Complex • (Complex::* const CPMFR) (const Complex &) const;
• CPMFR cp = Complex::operator*;• // В об’єкті z1 беремо метод, на який вказує• // указник cp, і застосовуємо його до об’єкту z2• cout<<(z1.*cp)(z2)<<endl;
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 8
Приклад. Текстовий екран
• // Текстовий екран максимальним розміром• // maxHeigh х maxWidth• class Screen• {• public:• // Екран заповнюється рядком pc,• // якщо він заданий, інакше він наповнюється• // наповнювачем _filler• Screen(int, int, char* pc =0);• ~Screen();• };
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 9
Атрибути екрану
• private:• // Наповнювач• static const char _filler;• // Фактична висота екрану• int _height;• // Фактична ширина екрану• int _width;• // Наповнення екрану• char *_wContent;• // Курсор• mutable int _cursor;
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 10
Перевести курсор в початок екрану
• Screen& Screen::home()• {• _cursor=0;• return *this;• };• // Сталий метод• const Screen& Screen::home() const• {• _cursor=0;• return *this;• };
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 11
Несуттєві атрибути
Виділимо атрибути, які з точки зору розробника не впливають на стан об'єкту
Якщо розробник вважає, що стан екрану виражається його наповненням, а не місцем розташування курсору, то визначимо відповідний атрибут як несуттєвий
• // Курсор (несуттєвий атрибут)• mutable int _cursor;
Несуттєві атрибути дозволяється модифікувати навіть у сталих об'єктів
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 12
Парні методи
• const Screen& home() const;• Screen& home();• const Screen& move() const;• Screen& move();• const Screen& move(int, int) const;• Screen& move(int, int);• const Screen& back() const;• Screen& back();• const Screen& show() const;• Screen& show();
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 13
Непарні методи
• // Очистити екран• Screen& clear();• // Показати символ, на якому знаходиться курсор• // непарний метод для ілюстрації проблеми• const Screen& showCurrent() const;• // Селектор• char get() const;• // Модифікатор• Screen& set(char);
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 14
Для чого потрібні парні методи?
• Screen v(4,4,"1111222233334444");• v.show().set('*').• // Screen& move(int, int); тому можна застосувати set• move(1,1).set('*').• move(2,2).set('*').• // showCurrent().• // непарна функція, тому застосувати set не можна• // const Screen& showCurrent() const;• move(3,3).set('*').• show();
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 15
Сталий результат
До сталого результату можна застосовувати лише сталі методи
• const Screen cv(5,5,"aaaaabbbbbcccccdddddeeeee");• cv.show().move(1,1).showCurrent().• move(2,2).showCurrent().• move(3,3).showCurrent().• show();
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 16
Указники екранних методів
Указник довільного методу
• typedef Screen& (Screen::* const NonConstAction) ();
Указник сталого методу
• typedef const Screen& • (Screen::* const ConstAction) () const;
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 17
Застосування указника методу
• // Застосувати до екрану s метод act n разів• void doAction• (Screen& s, Action act, int n)• {• for (int i=0; i<n; i++)• (s.*act)();• }
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 18
Застосування указника сталого методу
• // Застосувати до екрану s сталий метод act n разів• void doActionConst• (const Screen& s, ConstAction act, int n)• {• for (int i=0; i<n; i++)• (s.*act)();• }
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 19
Застосування: програмування меню
• // Меню екранних операцій• const ConstAction menuConst[] = • {• Screen::home,• Screen::move,• Screen::back,• Screen::show• };
• // Вибір операції із меню• doActionConst(cv, menuConst[k], n);
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 20
Указники в об'єктах
Доступ до об'єкта за указником• T * p = new T;• // a атрибут T• p -> a;
Доступ до методу за указником• T * p = new T;• // pf указник методу T• p ->* pf;
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 21
Приклад. Калькулятор
• // Кишеньковий калькулятор• class Calc • {• private:• // Accumulator• unsigned int a;• // Register• unsigned int x;• public:• // Виконати операцію• unsigned int exe (unsigned int (Calc::* ) ());• };
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 22
Реалізація операції калькулятора
• // Виконати операцію op()• unsigned int Calc::exe (unsigned int (Calc::*op) ())• {• return (this->*op)();• }
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 23
Указник атрибуту
• // Указник будь-якого регістру в калькуляторі• typedef unsigned int Calc::*Register;
• // Указник регістру а в якомусь калькуляторі• Register ra = &Calc::a;
• // Указник регістру x в якомусь калькуляторі• Register rx = &Calc::x;
• // і сам калькулятор• Calc c;
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 24
Застосування указника атрибуту
• // Циклічний зсув довільного регістру калькулятора• void cycleShiftL• // Передаємо регістр довільного калькулятора• (unsigned int Calc::*regPtr, Calc & c, int n)• {• // Працюємо з переданим регістром калькулятора с• for (int i= 0; i<n; ++i)• c.*regPtr = (c.*regPtr >> 31)|(c.*regPtr<<=1);• }• cycleShiftL(ra, c, 5); //регістр а зсунути на 5• cycleShiftL(rx, c, 10); //регістр х зсунути на 10
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 25
Указники статичних членів класу
Практично не відрізняються від звичайних
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 26
Приклад. Банк
• class Bank• {• friend class CurrentAccount;• private:• const int _bankId;• static double _normalInterestRate;• static double _advancedInterestRate;• static double _goldInterestRate;• public:• static void raiseInterest(CurrentAccount& account);• };
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 27
Приклад. Поточний рахунок
• class CurrentAccount• {• private:• const int _accountNo;• static const _freeAccountNo;• const Date _openingDate;• int _balance;• const int & _bankId;• const double * _interestRatePtr;• void (* _raiseInterestPtr) (CurrentAccount&);• };
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 28
Приклад. Конструктор
• CurrentAccount(const Bank & bank, int initBalance):• _accountNo(_freeAccountNo),• _balance(initBalance),• _bankId(bank.getId()),• // статичний атрибут банку• _interestRatePtr (&Bank::_normalInterestRate),• // статичний метод банку• // void (*) (CurrentAccount&);• _raiseInterestPtr (&Bank::raiseInterest)• {• ………………………………………………….• };
© Бублик В.В. Програмування-2. Об'єктне програмування. Типізація об’єктів 29
Висновок
Типи позакласних функцій і нестатичних методів класу розрізняються за рахунок наявності чи відсутності можливості використовувати поточний об'єкт
Відсилаючи до статичних методів, вказуємо область імен класу
Нестатичні атрибути вимагають уточнення класу в своєму типі, оскільки для доступу до них необхідно знати об'єкт
Тип статичних атрибутів від класу не залежить