Оператор перегрузки ->
Вот мой пример кода:
class X
{
public:
void f() {}
};
class Y : public X
{
public:
X& operator->() { return *this; }
void f() {}
};
int main()
{
Y t;
t.operator->().f(); // OK
t->f(); // error C2819: type 'X' does not have an overloaded member 'operator ->'
// error C2232: '->Y::f' : left operand has 'class' type, use '.'
}
Почему компилятор пытается "переместить ответственность" для оператора- > от Y до X? Когда я реализую X:: op- > , то я не могу вернуть X там - ошибка компиляции говорит о "бесконечной рекурсии", а при возвращении некоторого Z из X:: op- > снова говорит, что Z не имеет оператора- > , таким образом, выше и выше в иерархии.
Может ли кто-нибудь объяснить это интересное поведение?:)
Ответы
Ответ 1
Проблема заключается в том, что operator ->
должен возвращать указатель, а не ссылку. Идея состоит в том, что operator ->
должен возвращать указатель на реальный объект, который должен иметь указатель, применяемый к нему. Например, для класса с перегруженным operator ->
код
myClass->myValue;
означает
(myClass.operator-> ())->myValue;
Проблема с вашим кодом заключается в том, что operator ->
возвращает ссылку, поэтому запись
myClass.operator->().f();
является совершенно законным, потому что вы явно вызываете оператор, но пишите
myClass->f();
является незаконным, поскольку компилятор пытается его расширить до
myClass.operator->()->f();
и возвращаемый тип operator->
не является указателем.
Чтобы исправить это, измените код, чтобы вернуть указатель в operator ->
. Если вы хотите перегрузить оператор, чтобы вернуть ссылку, перегрузите operator *
; Различия в указателях действительно должны давать ссылки.
Ответ 2
Потому что как перегруженный ->
работает в С++.
При использовании перегруженного ->
выражение a->b
переводится в a.operator->()->b
. Это означает, что ваш перегруженный оператор ->
должен вернуть то, что само по себе поддерживает другое приложение оператора ->
. По этой причине один вызов перегруженного ->
может превратиться в длинную цепочку вызовов перегруженного ->
, пока он не достигнет приложения встроенного ->
, которое завершает цепочку.
В вашем случае вам нужно вернуть X*
из вашего перегруженного ->
, а не X&
.
Ответ 3
Синтаксис неверен:
Т > Т2
T2* T::operator ->();
Посмотрите на статью в википедии: Операторы на C и С++
Если вы хотите перегрузить, вы должны использовать правильный синтаксис для перегруженного оператора
Ответ 4
Вероятно, вы хотите:
class Y : public X
{
public:
X* operator->() { return this; }
void f() {}
};