->
Это единственный действительно хитрый. Это должна быть нестатическая функция-член, и она не принимает аргументов. Возвращаемое значение используется для поиска члена.
Если возвращаемое значение является другим объектом типа класса, а не указателем, то последующий поиск члена также обрабатывается функцией operator->
. Это называется «поведением детализации». Язык связывает воедино вызовы operator->
, пока последний не вернет указатель.
struct client
{ int a; };
struct proxy {
client *target;
client *operator->() const
{ return target; }
};
struct proxy2 {
proxy *target;
proxy &operator->() const
{ return * target; }
};
void f() {
client x = { 3 };
proxy y = { & x };
proxy2 z = { & y };
std::cout << x.a << y->a << z->a; // print "333"
}
->*
Этот хитр только в том, что в этом нет ничего особенного. Для версии без перегрузки требуется объект указателя на тип класса слева и объект указателя на тип члена справа. Но когда вы его перегружаете, вы можете принять любые аргументы и вернуть все, что захотите. Он даже не должен быть нестатическим членом.
Другими словами, это обычный бинарный оператор, такой как +
, -
и /
. Смотрите также: Является ли свободный оператор -> * перегрузкой зла?
.*
и .
Они не могут быть перегружены. Уже есть встроенное значение, когда левая часть имеет тип класса. Возможно, было бы немного разумно определить их для указателя на левой стороне, но комитет по разработке языка решил, что это будет скорее запутанно, чем полезно.
Перегрузка ->
, ->*
, .
и .*
могут заполнять только те случаи, когда выражение будет неопределенным, оно никогда не сможет изменить значение выражения, которое будет допустимым без перегрузки.