Что особенного в operator-> и как оно работает? - PullRequest
2 голосов
/ 14 апреля 2020
#include <iostream>

class A
{
public:

    int a;
    int b;
    int c;
    int d;
};

class B
{
    A a;

public:

    B(int a, int b, int c, int d) : a{ a, b, c, d } {}

    A* operator->()
    {
        return &a;
    }

    A* operator++(int)
    {
        return &a;
    }

    A* pointer()
    {
        return &a;
    }
};

int main()
{
    B b(1, 2, 3, 4);

    //std::cout << b->->a << ' ' << b->->b << ' ' << b->->c << ' ' << b->->d << std::endl;

    std::cout << b->a << ' ' << b->b << ' ' << b->c << ' ' << b->d << std::endl;

//  std::cout << b.pointer()a << ' ' << b.pointer()b << ' ' 
//              << b.pointer()c << ' ' << b.pointer()d << std::endl; 

    std::cout << b.pointer()->a << ' ' << b.pointer()->b << ' ' 
                << b.pointer()->c << ' ' << b.pointer()->d << std::endl; 

    //std::cout << b++a << ' ' << b++b << ' ' << b++c << ' ' << b++d << std::endl;

    std::cout << b++->a << ' ' << b++->b << ' ' << b++->c << ' ' << b++->d << std::endl;
}

Здесь в этом коде operator-> и функция pointer возвращают одно и то же. Но когда я вызываю operator->, я могу трактовать b, как если бы это был фактический указатель. Принимая во внимание, что если я вызываю функцию pointer, я должен использовать оператор стрелки для доступа к членам a. Это относится и к operator++. Это уникальное поведение только для operator->? Как работает operator->? 1011 *

Ответы [ 2 ]

4 голосов
/ 14 апреля 2020

Да, это специально для перегруженных operator->.

(выделено мое)

Если задан пользовательский оператор->, Оператор-> вызывается снова для значения, которое он возвращает, рекурсивно, пока не будет достигнут оператор->, который возвращает простой указатель. После этого встроенная семантика применяется к этому указателю .

Это означает, что доступ к элементу, такой как ->a, применяется к возвращенному указателю A* в конце концов.

1 голос
/ 14 апреля 2020

Как работает operator->?

Для указателя ptr->member является сокращением для (*ptr).member.

Если оператор-> перегрузка для возврата класса указатель на объект, тогда class_object->member эквивалентен pointer_returned_by_the_operator->member, что эквивалентно (*pointer_returned_by_the_operator).member согласно эквивалентности в предыдущем абзаце.

Помимо указателя, перегрузка оператора-> для класса может вернуть другой объект класса, который перегружает operator->. В таком случае operator-> применяется рекурсивно до тех пор, пока перегрузка не вернет указатель, и в этом случае применяется предыдущий абзац.

Перегрузки для унарного оператора * и operator-> разделены, но пока оператор -> возвращает указатель на тот же объект, на который оператор * возвращает ссылку, тогда та же поведенческая эквивалентность сохраняется между class_object->member и (*class_object).member - хотя они будут вызывать отдельные перегрузки операторов.

В вашем конкретном случае b->c эквивалентно b.a->c (где b.a вызывается в функции-члене), потому что перегруженный оператор возвращает указатель на this->a.

Это уникальное поведение только для оператора >?

Да.

...