Переменной ps_Screen разрешается присваивать указатель на _width или _height, так как они являются членами класса Screen типа short.

Несоответствие типов указателя на данные-члены и обычного указателя также связано с различием в их представлении. Обычный указатель содержит всю информацию, необходимую для обращения к объекту. Указатель на данные-члены следует сначала привязать к объекту или указателю на него, а лишь затем использовать для доступа к члену этого объекта. (В книге “Inside the C++ Object Model” ([LIPPMAN96a]) также описывается представление указателей на члены.)

Указатель на функцию-член определяется путем задания типа возвращаемого функцией значения, списка ее параметров и класса. Например, следующий указатель, с помощью которого можно вызвать функции height() и width(), имеет тип указателя на функцию-член класса Screen без параметров, которая возвращает значение типа int:

int (Screen::*)()

Указатели на функции-члены можно объявлять, инициализировать и присваивать:

// всем указателям на функции-члены класса можно присвоить значение 0

int (Screen::*pmf1)() = 0;

int (Screen::*pmf2)() = &Screen::height;

pmf1 = pmf2;

pmf2 = &Screen::width;

Использование typedef может облегчить чтение объявлений указателей на члены. Например, для типа “указатель на функцию-член класса Screen без параметров, которая возвращает ссылку на объект Screen”, т.е.

Screen& (Screen::*)()

Следующий typedef определяет Action как альтернативное имя:

typedef Screen& (Screen::*Action)();

Action default = &Screen::home;

Action next = &Screen::forward;

Тип "указатель на функцию-член" можно использовать для объявления формальных параметров и типа возвращаемого значения функции. Для параметра того же типа можно также указать значение аргумента по умолчанию:

Screen& action( Screen&, Action)();

action() объявлена как принимающая два параметра: ссылку на объект класса Screen и указатель на функцию-член Screen без параметров, которая возвращает ссылку на его объект. Вызвать action() можно любым из следующих способов:

Screen meScreen;

typedef Screen& (Screen::*Action)();

Action default = &Screen::home;

extern Screen& action( Screen&, Sction = &Screen::display );

void ff()

{

action( myScreen );

action( myScreen, default );

action( myScreen, &Screen::end );

}

В следующем подразделе обсуждается вызов функции-члена посредством указателя.

<p>13.6.2. Работа с указателями на члены класса</p>

К указателям на члены класса можно обращаться только с помощью конкретного объекта или указателя на объект типа класса. Для этого применяется любой из двух операторов доступа (.* для объектов класса и ссылок на них или -* для указателей). Например, так вызывается функция-член через указатель на нее:

int (Screen::*pmfi)() = &Screen::height;

Screen& (Screen::*pmfS)( const Screen& ) = &Screen::copy;

Screen myScreen, *bufScreen;

// прямой вызов функции-члена

if ( myScreen.height() == bufScreen-height() )

bufScreen-copy( myScreen );

// эквивалентный вызов по указателю

if ( (myScreen.*pmfi)() == (bufScreen-*pmfi)() )

(bufScreen-*pmfS)( myScreen );

Вызовы

(myScreen.*pmfi)()

(bufScreen-*pmfi)();

требуют скобок, поскольку приоритет оператора вызова () выше, чем приоритет взятия указателя на функцию-член. Без скобок

myScreen.*pmfi()

интерпретируется как

myScreen.*(pmfi())

Это означает вызов функции pmfi() и привязку возвращенного ей значения к оператору (.*). Разумеется, тип pmfi не поддерживает такого использования, так что компилятор выдаст сообщение об ошибке.

Указатели на данные-члены используются аналогично:

typedef short Screen::*ps_Screen;

Screen myScreen, *tmpScreen = new Screen( 10, 10 );

ps_Screen pH = &Screen::_height;

ps_Screen pW = &Screen::_width;

tmpScreen-*pH = myScreen.*pH;

tmpScreen-*pW = myScreen.*pW;

Перейти на страницу:

Похожие книги