C++ Перегрузка оператора доступа к членам класса ->

Перегрузка операторов и перегрузка функций в C++

Оператор доступа к членам класса (->) можно перегрузить, но это довольно хлопотно. Он определён для придания классу поведения "указателя". Оператор -> должен быть функцией-членом. Если используется оператор ->, возвращаемый тип должен быть указателем или объектом класса.

Оператор -> обычно используется в сочетании с оператором разыменования указателя * для реализации функциональности «умных указателей». Эти указатели являются объектами, которые ведут себя как обычные указатели, за исключением того, что при доступе к объекту через указатель они выполняют другие задачи. Например, когда указатель уничтожается или когда указатель указывает на другой объект, объект автоматически удаляется.

Оператор разыменования -> можно определить как унарный постфиксный оператор. То есть, для класса:

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

ClassPtrОбъекты могут использоваться для доступа к классам.XЕго члены используются способом, очень похожим на указатели. Например:

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

Инструкция p->m интерпретируется как (p.operator->())->m. Аналогично, следующий пример демонстрирует, как перегрузить оператор доступа к члену класса ->.

Пример

#include <iostream> #include <vector> using namespace std; // Предположим, есть реальный класс class Obj { static int i, j; public: void f() const { cout << i++ << endl; } void g() const { cout << j++ << endl; } }; // Определение статического члена int Obj::i = 10; int Obj::j = 12; // Реализовать контейнер для вышеуказанного класса class ObjContainer { vector<Obj*> a; public: void add(Obj* obj) { a.push_back(obj); // Вызвать стандартные методы vector } friend class SmartPointer; }; // Реализовать умный указатель для доступа к членам класса Obj class SmartPointer { ObjContainer oc; int index; public: SmartPointer(ObjContainer& objc) { oc = objc; index = 0; } // Возвращаемое значение указывает на конец списка bool operator++() // Префиксная версия { if(index >= oc.a.size() - 1) return false; if(oc.a[++index] == 0) return false; return true; } bool operator++(int) // Суффиксная версия { return operator++(); } // Перегрузка оператора -> Obj* operator->() const { if(!oc.a[index]) { cout << "Нулевое значение"; return (Obj*)0; } return oc.a[index]; } }; int main() { const int sz = 10; Obj o[sz]; ObjContainer oc; for(int i = 0; i < sz; i++) { oc.add(&o[i]); } SmartPointer sp(oc); // Создать итератор do { sp->f(); // Вызов умного указателя sp->g(); } while(sp++); return 0; }

Когда приведённый выше код скомпилирован и выполнен, он выдаст следующие результаты:

10
12
11
13
12
14
13
15
14
16
15
17
16
18
17
19
18
20
19
21

Перегрузка операторов и перегрузка функций в C++

Другие расширения