Вопрос по c++ – рекурсивное применение оператора->

7

Говорят, что оператор стрелки применяется рекурсивно. Но когда я пытаюсь выполнить следующий код, он печатает бред, когда должен печатать 4.

class dummy
{
public:
    int *p;

    int operator->()
    {
        return 4;
    }
};

class screen 
{
public:
    dummy *p;

    screen(dummy *pp): p(pp){}
    dummy* operator->()
    {
        return p;
    }
};

int main()
{
    dummy *d = new dummy;
    screen s(d);
    cout<<s->p;
    delete d;
}
Нет, я не согласен, ваш пример работает, как ожидалось, - & gt; По сути, opertor - это просто вызов функции, зачем его детализировать? Если это так, то как бы вы контролировали, на каком уровне прекратить разыменование, и это сделало бы наследование и полиморфизм еще более сложным, чем это уже есть? EdChum
Учебник по C ++, четвертое издание Стэнли Б. Липпман, раздел 14.6, последний абзац. user1232138
Где сказано, что он применяется рекурсивно? Matti Virkkunen

Ваш Ответ

3   ответа
11

рекурсивным & # x201D; просто оператор применяется к каждому возвращаемому объектуuntil возвращаемый тип - указатель.

Что происходит здесь с первой попытки:screen::operator -> возвращает указатель Таким образом, это последний вызовoperator -> что компилятор пытается. Затем он решает правую часть оператора (p) путем поиска члена в возвращенном типе pointee (dummy) с этим именем.

По сути, всякий раз, когда компилятор находит синтаксисaᵢ->b в коде по существу применяется следующий алгоритм:

Is aᵢ of pointer type? If so, resolve member b of *aᵢ and call (*aᵢ).b. Else, try to resolve aᵢ::operator -> On success, set aᵢ₊₁ = aᵢ::operator ->(). Goto 1. On failure, emit a compile error.

Мне трудно придумать короткий, содержательный пример, когдаchain изoperator -> вызовы даже имеют смысл. Вероятно, единственное реальное использование - это когда вы пишете класс умного указателя.

Тем не менее, следующий игрушечный пример по крайней мере компилирует и выдает число. Но я бы не советовал на самом деле писать такой код. Это нарушает инкапсуляцию и заставляет котят плакать.

#include <iostream>

struct size {
    int width;
    int height;
    size() : width(640), height(480) { }
};

struct metrics {
    size s;
    size const* operator ->() const {
        return &s;
    }
};

struct screen {
    metrics m;
    metrics operator ->() const {
        return m;
    }
};

int main() {
    screen s;
    std::cout << s->width << "\n";
}
Error: User Rate Limit Exceededsize::width).
Error: User Rate Limit Exceededoperator ->*Error: User Rate Limit Exceededstring representationError: User Rate Limit Exceeded
Error: User Rate Limit Exceededoperator -> mustError: User Rate Limit Exceeded
Error: User Rate Limit Exceededoperator->*Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded user1232138
2

C++ Primer (5-е издание) формулирует это следующим образом на странице 570:

The arrow operator never loses its fundamental meaning of member access. When we overload arrow, we change the object from which arrow fetches the specified member. We cannot change the fact that arrow fetches a member.

0

screen::operator->() возвращает указатель (dummy*) рекурсия останавливается, потому что встроенная (по умолчанию)-> используется на этом указателе. Если вы хотите рекурсию, вы должны вернутьсяdummy или жеdummy& отscreen::operator->()

Похожие вопросы