-› использование в умных указателях

У меня есть простая реализация интеллектуального указателя, показанная во фрагменте кода 1 ниже. И фиктивный тестовый класс с именем Dummy во втором фрагменте. Фрагмент кода 3 показывает, как мы можем использовать этот простой интеллектуальный указатель для доступа к функции foo().

Мой вопрос о том, как мы вызываем функцию foo() в классе Dummy с помощью оператора ->. -> оператор уже возвращает указатель на необработанный указатель. Итак, я думаю, чтобы мы могли вызвать функцию foo(), нам нужно выполнить вторую операцию -> над возвращенным необработанным указателем. Однако во многих источниках говорится, что достаточно просто одного использования оператора ->.

Вкратце, я думаю, что правильный вызов должен выглядеть следующим образом: (dummy->)->foo();

Однако такой вызов dummy->foo() работает нормально. Может кто-нибудь объяснить мне, почему (dummy->)->foo() неверен? Возможно, у меня есть концептуальное непонимание, но я хотел бы знать концепцию правильно.

ФРАГМЕНТ КОДА 1 (класс SMART POINTER)

template <typename T>
class SmartPointer
{
 private:
    T* mRawPointer;

 public:
    SmartPointer(T* thePointer) : mRawPointer(thePointer) {}
    ~SmartPointer() { delete mRawPointer;}

    T& operator* () const { return *mRawPointer; }

    T* operator-> () const { return mRawPointer; }

};

ФРАГМЕНТ КОДА 2 (фиктивный класс)

class Dummy
{
 public:
   foo() {......}
};

ФРАГМЕНТ КОДА 3 (ВАРИАНТЫ ВЫЗОВА В ВОПРОСЕ)

SmartPointer<Dummy> dummy(new Dummy());

(dummy->)->func(); 
//I think the above is correct cause we need to make a second dereference on the 
//returned raw pointer
//OR
dummy->func();

person F. Aydemir    schedule 14.11.2013    source источник
comment
Примечание. a->b определяется как (*a).b (для неперегруженных ->), поэтому (dummy->)->func() будет определяться как (*((*dummy).)).func(), что является нонсенсом.   -  person dyp    schedule 15.11.2013


Ответы (2)


Так оно и есть, потому что так написано в стандарте...

Выражение x->m интерпретируется как (x.operator->())->m для объекта класса x типа T, если существует T::operator->() и если оператор выбран как функция наилучшего соответствия по механизму разрешения перегрузок

person David    schedule 14.11.2013

Подумайте об этом так:

dummy-> фактически возвращает Dummy*. Стандарт допускает, что при перегрузке оператора->() достаточно одной стрелки, чтобы вывести 1) перегруженный оператор и 2) базовый необработанный указатель.

Без этого механизма у нас не было бы действительно «умных» указателей, поскольку синтаксис между этим и необработанным указателем был бы другим.

person syvex    schedule 14.11.2013