web-dev-qa-db-ja.com

C ++-[]演算子のオーバーロード

テンプレートクラスの配列があります。

_template <class T=int, int SIZE=10>
class Array {
    T TheArray[SIZE];
public:
    void Initialize() {
        for (int idx=0; idx < SIZE; idx++) {
            TheArray[idx] = T();
        }
    }

    T& operator [](int idx) {
        return TheArray[idx];
    }

    T operator [](int idx) const {
        return TheArray[idx];
    }
}
_

演算子_[]_のオーバーロードに関する質問があります(この例をネットで見つけました)。

T& operator [](int idx)がインデックスidxを持つ配列値への参照を返し、T operator [](int idx) constがその値を返すことを理解しています。ただし、_[]_演算子を使用して参照または値が返されるケースはわかりません。

また、T operator [](int idx) const-> T operator [](int idx)を変更すると、コンパイラーは文句を言います。何故ですか?戻り値の型のみが異なるため、コンパイラが文句を言うことは理解できますが、constを追加しても文句を言わないのはなぜですか?これは、クラス内部のどれも変更されないことを意味するだけですよね?

私はこの小さなメイン実装をデバッグしようとしました:

_int main() {
    int val;
    Array<> intArray;

    intArray.Initialize();
    val = intArray[1];
    printf("%d", intArray[1]);
    intArray[1] = 5;
}
_

そして、T& operator [](int idx)が呼び出されるたびに。どうして?

前もって感謝します。

13
Mojo28

operator[]オーバーロードは、呼び出し元のオブジェクトのconst-資格に基づいて選択されます。

Array<> intArray;
intArray[1]; //calls T& operator[]

const Array<> constArray;
constArray[1]; //calls T operator[]

T operator[]からconstを削除すると、メンバー関数は同じconst- qualificationとパラメーターを持つことができないため、それらを選択する方法がないため、エラーが発生します。

15
TartanLlama

最初に、_[]_を_this->operator[]_を呼び出すための構文シュガーと見なします。

constthisポインターの場合はconstバージョンが呼び出され、そうでない場合はconstバージョンが呼び出されます。

次に、const T& operator [](int idx) const {を使用する必要があります。つまり、constバージョンがconst参照を返すようにします。これにより、ディープコピーを作成するオーバーヘッドが節約されます。

最後に、関数のconst- ness isその署名の一部。これにより、const- nessに基づいてオーバーロードできます。そうしないと、_operator[]_の2つのバージョンを使用できません。

12
Bathsheba