Подтвердить что ты не робот

Оператор перегрузки ->

Вот мой пример кода:

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 не имеет оператора- > , таким образом, выше и выше в иерархии.

Может ли кто-нибудь объяснить это интересное поведение?:)

4b9b3361

Ответ 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() {}
};