Язык программирования C++ для профессионалов

       

Косвенное обращение


Операцию косвенного обращения к члену -> можно определить как унарную постфиксную операцию. Это значит, если есть класс

class Ptr { // ... X* operator->(); };

объекты класса Ptr могут использоваться для доступа к членам класса X также, как для этой цели используются указатели:

void f(Ptr p) { p->m = 7; // (p.operator->())->m = 7 }

Превращение объекта p в указатель p.operator->() никак не зависит от члена m, на который он указывает. Именно по этой причине operator->() является унарной постфиксной операцией. Однако, мы не вводим новых синтаксических обозначений, так что имя члена по-прежнему должно идти после -> :

void g(Ptr p) { X* q1 = p->; // синтаксическая ошибка X* q2 = p.operator->(); // нормально }

Перегрузка операции -> прежде всего используется для создания "хитрых указателей", т.е. объектов, которые помимо использования как указатели позволяют проводить некоторые операции при каждом обращении к указуемому объекту с их помощью. Например, можно определить класс RecPtr для организации доступа к объектам класса Rec, хранимым на диске. Параметром конструктора RecPtr является имя, которое будет использоваться для поиска объекта на диске. При обращении к объекту с помощью функции RecPtr::operator->() он переписывается в основную память, а в конце работы деструктор RecPtr записывает измененный объект обратно на диск.

class RecPtr { Rec* in_core_address; const char* identifier; // ... public: RecPtr(const char* p) : identifier(p) { in_core_address = 0; } ~RecPtr() { write_to_disc(in_core_address,identifier); } Rec* operator->(); };

Rec* RecPtr::operator->() { if (in_core_address == 0) in_core_address = read_from_disc(identifier); return in_core_address; }

Использовать это можно так:

main(int argc, const char* argv) { for (int i = argc; i; i--) { RecPtr p(argv[i]); p->update(); } }

На самом деле, тип RecPtr должен определяться как шаблон типа (см. §8), а тип структуры Record будет его параметром. Кроме того, настоящая программа будет содержать обработку ошибок и взаимодействие с диском будет организовано не столь примитивно.

Для обычных указателей операция -> эквивалентна операциям, использующим * и []. Так, если описано



Содержание раздела