Перегрузка квадратных скобок => ни один оператор не соответствует операндам

В настоящее время у меня возникают проблемы с перегрузкой квадратных скобок в пользовательском векторном классе.

Мой класс в основном выглядит так:

typedef uint32_t u32; // This is not actually here, but so you get the idea. Also, it is included in the problematic call's file

template<class T>
class JFFVector
{
public:
    //Init and stuff
    T& operator[](u32 iIndex)
    {
        return m_pData[iIndex + miDataOffset];
    }

private:
    T* m_pData;
    u32 m_iDataOffset;
}

И внутри этих функций классов я могу вызвать (*this)[0] и все работает. Теперь проблема, с которой я сталкиваюсь, связана с классом, в котором есть член следующим образом:

class TOtherClass
{
public:
    // Stuff
    void DoSomething() const
    {
        for (u32 i; i < m_tItems.size(); ++i)
            m_tItems[i]->DoStuff(); // Which is a const function
    }

private:
    JFFVector<const JFFItem*> m_tItems;
}

Проблема в том, что мой компилятор выдает ошибку на моем лице, говоря

ни один оператор "[]" не соответствует этим операндам

типы операндов: const JFFVector[u32]

typedef uint32_t u32.

Итак, одна вещь, которую я заметил, это то, что если я делаю m_tItems указателем, то я могу сделать "(*m_tItems)[i]->DoStuff()", и это работает нормально. Но я не понимаю, почему это работает, а не с версией без указателя. (Кроме того, я попробовал использовать простой int вместо u32, и, что неудивительно, это не сработало)

Кто-нибудь знает, что я сделал неправильно, пожалуйста? И, если не тривиально, то почему неправильно?

(Извините, если на этот вопрос уже был дан ответ, я пытался найти похожую проблему, но не нашел ничего похожего на эту проблему)


person Thex    schedule 22.11.2016    source источник


Ответы (3)


Есть два оператора индексации, которые вы можете перегрузить: один работает с const JFFVector и возвращает T const&, а другой работает с JFFVector и возвращает T&. Вы реализовали только второй.

Вы можете реализовать его аналогично неконстантной версии, например:

T const& operator[](u32 iIndex) const   // <-- note the two `const`s
{
    return m_pData[iIndex + miDataOffset];
}

Обратите внимание, что эта перегрузка относится не только к operator[], но и ко всем методам (которые могут быть перегружены const или не const).

Причина, по которой вам нужна версия const в вашем коде, заключается в том, что DoSomething() объявлен как const, поэтому this является const TOtherClass* в этом методе, и, соответственно, все его члены, особенно m_tItems здесь, являются const внутри метода, и поэтому могут быть вызваны только const методы. на них. Поскольку для m_tItems не существует const версии operator[], компилятор выдает эту ошибку.

person Cameron    schedule 22.11.2016
comment
Верно. Даюм. Я действительно попался на эту ошибку. Спасибо друг! - person Thex; 23.11.2016

Находясь в const, нужно оставаться const. У компилятора нет простого способа узнать, что то, что происходит в m_tItems[i], не меняет m_tItems и, таким образом, нарушает обещание, что void DoSomething() const не изменит состояние TOtherClass.

Решение: внедрить const operator[]

const T& operator[](u32 iIndex) const 
{
    return m_pData[iIndex + miDataOffset];
}
person user4581301    schedule 22.11.2016

Вам нужны 2 версии, одна для const и одна без const. Один для неизменного const JFFVector и один для изменяемого JFFVector.

В этом случае DoSomething является константной функцией, она хочет вызвать константную функцию.

template<class T>
class JFFVector
{
public:
    //Init and stuff
    T& operator[](u32 iIndex)
    {
        return m_pData[iIndex + miDataOffset];
    }
    const T& operator[](u32 iIndex) const
    {
        return m_pData[iIndex + miDataOffset];
    }

private:
    T* m_pData;
    u32 m_iDataOffset;
}
person Danh    schedule 22.11.2016