Указатель на член класса
Предположим, что в нашем классе Screen
определены четыре новых функции-члена: forward(), back(), up() и down(), которые перемещают курсор соответственно вправо, влево, вверх и вниз. Сначала мы должны объявить их в теле класса:
class Screen { public: inline Screen& forward(); inline Screen& back(); inline Screen& end(); inline Screen& up(); inline Screen& down(); // другие функции-члены не изменяются private: inline int row(); // другие функции-члены не изменяются |
};
Функции-члены forward() и back()
перемещают курсор на один символ. По достижении правого нижнего или левого верхнего угла экрана курсор переходит в противоположный угол.
inline Screen& Screen::forward() { // переместить _cursor вперед на одну экранную позицию ++_cursor; // если достигли конца экрана, перепрыгнуть в противоположный угол if ( _cursor == _screen.size() ) home(); return *this; } inline Screen& Screen::back() { // переместить _cursor назад на одну экранную позицию // если достигли начала экрана, перепрыгнуть в противоположный угол if ( _cursor == 0 ) end(); else --_cursor; return *this; |
}
end()
перемещает курсор в правый нижний угол экрана и является парной по отношению к функции-члену home():
inline Screen& Screen::end() { _cursor = _width * _height - 1; return *this; |
}
Функции up() и down()
перемещают курсор вверх и вниз на одну строку. По достижении верхней или нижней строки курсор остается на месте и подается звуковой сигнал:
const char BELL = '\007'; inline Screen& Screen::up() { // переместить _cursor на одну строку вверх // если уже наверху, остаться на месте и подать сигнал if ( row() == 1 ) // наверху? cout << BELL << endl; else _cursor -= _width; return *this; } inline Screen& Screen::down() { if ( row() == _height ) //внизу? cout << BELL << endl; else _cursor += _width; return *this; |
}
row() – это закрытая функция-член, которая используется в функциях up() и down(), возвращая номер строки, где находится курсор:
inline int Screen::row() { // вернуть текущую строку return ( _cursor + _width ) / height; |
Пользователи класса Screen
попросили нас добавить функцию repeat(), которая повторяет указанное действие n
раз. Ее реализация могла бы выглядеть так:
Screen &repeat( char op, int times ) { switch( op ) { case DOWN: // n раз вызвать Screen::down() break; case DOWN: // n раз вызвать Screen::up() break; // ... } |
Такая реализация имеет ряд недостатков. В частности, предполагается, что функции-члены класса Screen
останутся неизменными, поэтому при добавлении или удалении функции-члена repeat()
необходимо модифицировать. Вторая проблема – размер функции. Поскольку приходится проверять все возможные функции-члены, то исходный текст становится громоздким и неоправданно сложным.
В более общей реализации параметр op
заменяется параметром типа указателя на функцию-член класса Screen. Теперь repeat() не должна сама устанавливать, какую операцию следует выполнить, и всю инструкцию switch
можно удалить. Определение и использование указателей на члены класса – тема последующих подразделов.