В C++ предусмотрена возможность сгенерировать указатель специального типа, который "ссылается"
не на конкретный экземпляр члена в объекте, а на член класса вообще. Указатель такого типа называется указателем на член класса (pointer-to-member). Это — не обычный С++-указатель. Этот специальный указатель обеспечивает только соответствующее смещение в объекте, которое позволяет обнаружить нужный член класса. Поскольку указатели на члены — не настоящие указатели, к ним нельзя применять операторы "." и "->". Для получения доступа к члену класса через указатель на член необходимо использовать специальные операторы ".*" и "->*".Если идея, изложенная в предыдущем абзаце, вам показалась немного "туманной"
, то следующий пример поможет ее прояснить. При выполнении этой программы отображается сумма чисел от 1 до 7. Здесь доступ к членам класса myclass (функции sum_it() и переменной sum) реализуется путем использования указателей на члены.
// Пример использования указателей на члены класса.
#include
using namespace std;
class myclass {
public:
int sum;
void myclass::sum_it(int x);
};
void myclass::sum_it(int x) {
int i;
sum = 0;
for(i=x; i; i--) sum += i;
}
int main()
{
int myclass::*dp; // указатель на int-член класса
void (myclass::*fp)(int x); // указатель на функцию-член
myclass с;
dp = &myclass::sum; // получаем адрес члена данных
fp = &myclass::sum_it; // получаем адрес функции-члена
(c.*fp)(7); // вычисляем сумму чисел от 1 до 7
cout << "Сумма чисел от 1 до 7 равна " << с.*dp;
return 0;
}
Результат выполнения этой программы таков.
Сумма чисел от 1 до 7 равна 28
В функции main() создается два члена-указателя: dp
(для указания на переменную sum) и fp (для указания на функцию sum_it()). Обратите внимание на синтаксис каждого объявления. Для уточнения класса используется оператор разрешения контекста (оператор разрешения области видимости). Программа также создает объект типа myclass с именем с.Затем программа получает адреса переменной sum
и функции sum_it() и присваивает их указателям dp и fp соответственно. Как упоминалось выше, эти адреса в действительности представляют собой лишь смещения в объекте типа myclass, по которым можно найти переменную sum и функцию sum_it(). Затем программа использует указатель на функцию fp, чтобы вызвать функцию sum_it() для объекта с. Наличие дополнительных круглых скобок объясняется необходимостью корректно применить оператор ".*". Наконец, программа отображает значение суммы чисел, получая доступ к переменной sum объекта с через указатель dp.При доступе к члену объекта с помощью объекта или ссылки на него необходимо использовать оператор ".*"
. Но если для этого используется указатель на объект, нужно использовать оператор "->*", как показано в этой версии предыдущей программы.
#include
using namespace std;
class myclass {
public:
int sum;
void myclass::sum_it(int x);
};
void myclass::sum_it(int x) {
int i;
sum = 0;
for(i=x; i; i--) sum += i;
}
int main()
{
int myclass::*dp; // указатель на int-член класса
void (myclass::*fp)(int x); // указатель на функцию-член
myclass *c, d; // член с сейчас -- указатель на объект
с = &d // присваиваем указателю с адрес объекта
dp = &myclass::sum; // получаем адрес члена данных sum
fp = &myclass::sum_it; // получаем адрес функции sum_it()
(c->*fp) (7); // Теперь используем оператор для вызова функции sum_it().
cout << "Сумма чисел от 1 до 7 равна " << c->*dp; // ->*
return 0;
}
В этой версии переменная с
объявляется как указатель на объект типа myclass, а для доступа к члену данных sum и функции-члену sum_it() используется оператор "->*".