В 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() используется оператор "->*".

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

Все книги серии Изучайте C++ с профессионалами

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