Семантика указателя C++. Почему operator-> не возвращает указатель как положено

Рейтинг: 0Ответов: 1Опубликовано: 24.02.2023
class Foo
{
public:
    void foo() const { std::cout << "foo" << std::endl; }
};

template <class T>
class UniqPtr
{
private:
    T* ptr_;
public:
    UniqPtr(T* ptr) : ptr_(ptr) {}
    
    T* operator-> () { return ptr_; }

    ~UniqPtr() { delete ptr_; }
};

int main()
{
    UniqPtr<UniqPtr<Foo>> q(new UniqPtr<Foo>(new Foo()));
    (q->)->foo(); // ERROR
}

Почему я не могу сделать так? Это же вроде логично...

Ответы

▲ 1Принят

Первая стрелка возвращает указатель и он имеет тип UniqPtr<Foo>*, а класс UniqPtr<Foo> не имеет метода foo и происходит ошибка. Вам нужно ещё разыменование указателя с помощью звёздочки, чтобы получить сам объект . Примерно так :

(*(q->))->foo();    

Но данная запись опять приведёт к ошибке, так как укороченный вариант (q->) требует только метод или поле. Работать будет только в простых случаях.

В вашем случае укороченный вариант пропускаем и вызываем прямой вызов оператора так :

(*(q.operator->()))->foo();

Вариант II

q->operator->()->foo();

q-> возвращает тип UniqPtr<Foo>*
operator->() возвращает тип Foo*
->foo() уже вызывает метод.