С++ для начинающих

       

Указатель на член класса


Предположим, что в нашем классе 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 можно удалить. Определение и использование указателей на члены класса – тема последующих подразделов.


Содержание раздела