Выбрать главу

void (*psf)(double) = &Account::raiseInterest;

psf( 0.0025 );

}

Account ac1( 5000, "Asterix" );

Account ac2( 10000, "Obelix" );

if ( compareRevenue( ac1, &ac2 ) & 0 )

cout ac1.owner()

"is richer than "

ac2.owner() "\n";

else

cout ac1.owner()

" is poorer than"

ac2.owner() "\n";

return 0;

}

Упражнение 13.8

Пусть дан класс Y с двумя статическими данными-членами и двумя статическими функциями-членами:

class X {

public:

X( int i ) { _val = i; }

int val() { return _val; }

private:

int _val;

};

class Y {

public:

Y( int i );

static X xval();

static int callsXval();

private:

static X _xval;

static int _callsXval;

};

Инициализируйте _xval значением 20, а _callsXval значением 0.

Упражнение 13.9

Используя классы из упражнения 13.8, реализуйте обе статические функции-члена для класса Y. callsXval() должна подсчитывать, сколько раз вызывалась xval().

Упражнение 13.10

Какие из следующих объявлений и определений статических членов ошибочны? Почему?

// example.h

class Example {

public:

static double rate = 6.5;

static const int vecSize = 20;

static vectordouble vec(vecSize);

};

// example.c

#include "example.h "

double Example::rate;

vectordouble Example::vec;

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

Предположим, что в нашем классе 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() необходимо модифицировать. Вторая проблема – размер функции. Поскольку приходится проверять все возможные функции-члены, то исходный текст становится громоздким и неоправданно сложным.