Вопрос

Этот вопрос уже имеет ответ здесь:

Моя проблема простая. У меня есть шаблон класса, который имеет указатель на динамически выделенный тип. Я хочу перегрузить оператора косвенности так, чтобы ссылаться на экземпляр шаблона класса с помощью оператора ->, который я перенаправляю, как если бы я использовал указатель, содержащийся непосредственно.

template<class T>
class MyClass
 {
  T *ptr;
  ...
  // created dynamic resource for ptr in the constructor
 };

Создайте MyClass какого -то типа:

MyClass<SomeObject> instance;

Так что я хочу, чтобы вместо того, чтобы печатать:

instance.ptr->someMemberMethod();

Я просто печатаю:

intance->someMemberMethod();

Даже ты instance это не указатель, он ведет себя так, как будто это указатель instance содержит. Как преодолеть этот разрыв, перегружая оператора?

Это было полезно?

Решение

Вы можете просто перегрузить operator-> а также operator*:

template<class T>
class MyClass
{
    T* ptr;

public:
    T* operator->() {
        return ptr;
    }

    // const version, returns a pointer-to-const instead of just a pointer to
    // enforce the idea of the logical constness of this object 
    const T* operator->() const {
        return ptr;
    }

    T& operator*() {
        return *ptr;
    }

    // const version, returns a const reference instead of just a reference
    // to enforce the idea of the logical constness of this object
    const T& operator*() const {
        return *ptr;
    }
};

Обратите внимание, что из -за разработного решения создателя языка вы не можете перегрузить . оператор.

Кроме того, вы можете подумать, что operator* перегрузил умножение оператор вместо оператора Dereference. Однако это не так, потому что оператор умножения берет один аргумент (в то время как оператор Dereference не принимает аргументов), и из -за этого компилятор может сказать, какой есть какой.

Наконец, обратите внимание, что operator-> возвращает указатель, но operator* Возвращает ссылку. Легко их случайно запутать их.

Другие советы

Перегрузить -> оператор:

template <typename T> class MyClass
{
    T * p;
public:
    T       * operator->()       { return p; }  // #1
    T const * operator->() const { return p; }
};

Обратите внимание, что оба Перегрузки не мутируют объект; Тем не менее, мы решаем сделать № 1 не консервативным, чтобы мы завещали постоянность объекта на точки. Иногда это называется «глубоким распространением константы» или чем -то в этом роде. Язык D занимает намного дальше.

Оператор доступа к участнику может быть перегружен, чтобы вернуть указатель на объект, который будет доступен:

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

Вы также можете захотеть оператора уважения, чтобы он чувствовал себя еще больше как указатель; Вместо этого это возвращает ссылку:

T & operator*() {return *ptr;}
T const & operator*() const {return *ptr;}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top