Ответ 1
Перегрузка разрыва оператора (*
) работает как любая другая перегрузка оператора. Если вы хотите изменить значение разыменования, вам нужно вернуть неконстантную ссылку. Таким образом, *sp = value
фактически изменит значение, на которое указывает sp.pData
, а не временное значение, сгенерированное компилятором.
Перегрузка оператора структурного разыменования (->
) является частным случаем перегрузки оператора. Оператор фактически вызывается в цикле до тех пор, пока не будет возвращен реальный указатель, а затем этот реальный указатель будет разыменован. Я предполагаю, что это был единственный способ, которым они могли придумать, чтобы реализовать его, и это оказалось немного хаки. Однако у него есть некоторые интересные свойства. Предположим, что у вас были следующие классы:
struct A {
int foo, bar;
};
struct B {
A a;
A *operator->() { return &a; }
};
struct C {
B b;
B operator->() { return b; }
};
struct D {
C c;
C operator->() { return c; }
};
Если у вас есть объект d
типа d
, вызов d->bar
сначала вызовет D::operator->()
, затем C::operator->()
, а затем B::operator->()
, который, наконец, вернет реальный указатель на struct A
, и его член bar
разыменован обычным образом. Обратите внимание, что в следующем:
struct E1 {
int foo, bar;
E1 operator->() { return *this; }
};
Вызов e->bar
, где e
имеет тип E1
, создает бесконечный цикл. Если вы действительно хотите разыменовать e.bar
, вам нужно будет сделать это:
struct E2 {
int foo, bar;
E2 *operator->() { return this; }
};
Подводя итог:
- При перегрузке оператора разыменования тип должен быть
T&
, потому что это необходимо для изменения значения, на которое указываетpData
. - При перегрузке разыменования структуры тип должен быть
T*
, потому что этот оператор является частным случаем, и именно так оно и работает.