Концептуально эти операторы выполняют два действия: обращаются к значению указателя на член класса, чтобы получить доступ к необходимому члену; затем, подобно операторам обращения к членам, они обращаются к члену данного объекта непосредственно (.*
) или через указатель (->*
).
К указателям на члены применимы обычные средства управления доступом. Например, член contents
класса Screen
является закрытым. В результате указатель pdata
выше должен использоваться в члене класса Screen
, его дружественном классе, либо произойдет ошибка.
Поскольку переменные-члены обычно являются закрытыми, как правило, нельзя получать указатель на саму переменную-член. Вместо этого, если такой класс, как Screen
, желает предоставить доступ к своему члену contents
, то он определил бы функцию, возвращающую указатель на эту переменную-член:
class Screen {
public:
//
static const std::string Screen::*data()
{ return &Screen::contents; }
//
};
Здесь в класс Screen
добавлена статическая функция-член, возвращающая указатель на переменную-член contents
класса Screen
. Тип возвращаемого значения этой функции совпадает с типом первоначального указателя pdata
. Читая тип возвращаемого значения справа налево, можно заметить, что функция data()
возвращает указатель на член класса Screen
, имеющий тип string
и являющийся константой. Тело функции применяет оператор обращения к адресу к переменной-члену contents
. Таким образом, функция возвращает указатель на переменную-член contents
класса Screen
.
Когда происходит вызов функции data()
, возвращается указатель на член класса:
//
const string Screen::*pdata = Screen::data();
Как и прежде, указатель pdata
указывает на член класса Screen
, но не на фактические данные. Чтобы использовать указатель pdata
, следует связать его с объектом типа Screen
:
//
auto s = myScreen.*pdata;
Упражнение 19.11. В чем разница между обычным указателем на данные и указателем на переменную-член?
Упражнение 19.12. Определите указатель на член класса, способный указывать на член cursor
класса Screen
. Получите через этот указатель значение Screen::cursor
.
Упражнение 19.13. Определите тип, способный представить указатель на член bookNo
класса Sales_data
.
19.4.2. Указатели на функции-члены
Вполне можно также определить указатель, способный указывать на функцию-член класса. Подобно указателям на переменные-члены, самый простой способ создания указателя на функцию-член — это использовать ключевое слово auto
для автоматического выведения типа:
//
//
auto pmf = &Screen::get_cursor;
Как и указатель на переменную-член, указатель на функцию-член объявляется с использованием синтаксиса
. Подобно любому другому указателю на функцию (см. раздел 6.7), указатель на функцию-член определяет тип возвращаемого значения и список типов параметров функции, на которую может указывать этот указатель. Если функция-член является константной (см. раздел 7.1.2) или ссылочной (см. раздел 13.6.3), следует также добавить квалификатор const
или квалификатор ссылки.
Подобно обычным указателям на функцию, если функция-член перегружена, следует явно указать, какая именно функция имеется в виду (см. раздел 6.7). Например, указатель на версию функции get()
с двумя параметрами можно объявить так:
char (Screen::*pmf2)(Screen::pos, Screen::pos) const;
pmf2 = &Screen::get;
Круглые скобки вокруг части Screen::*
в этом объявлении необходимы из-за приоритета. Без круглых скобок компилятор воспримет следующий код как (недопустимое) объявление функции:
//
//
char Screen::*p(Screen::pos, Screen::pos) const;