оператор [] разрешение неоднозначности

нуб здесь. Ниже приведен фрагмент определения класса, с которым я столкнулся в примере с книгой:

double& operator[](int i);
double operator[](int i) const;

Мой вопрос: почему это не двусмысленно? При компиляции файлов проекта компилятор не выдает никакой ошибки.
Кроме того, в следующем (представьте, что AnyClass содержит valarray<double> объект, например, и я хочу получить к нему доступ напрямую):

AnyClass test;
cout << test[2]

какую версию использует компилятор?

1

Решение

Это не двусмысленно, потому что const является частью подписи и может использоваться для разрешения перегрузки. Так что если вы используете operator[] на неконстантном объекте он выбирает перегрузку без const потому что это самый конкретный. И если вы используете его на const объекте, он выбирает перегрузку с const потому что это единственный, который применяется.

7

Другие решения

Если вызвано на const объект, const версия будет использоваться, иначе другая.

Вот как компилятор разрешает неоднозначность.

1

AnyClass test;
const AnyClass const_test;
std::cout << test[2];       // calls operator[](int)
std::cout << const_test[2]; // calls operator[](int) const
1

Чтобы понять это, в основном вам просто нужно понять, что const по аргументу достаточно для устранения неоднозначности вызова:

#include <iostream>

void foo(char* ptr)
{
std::cout << "mutable: " << ptr << std::endl;
}

void foo(const char* ptr)
{
std::cout << "const: " << ptr << std::endl;
}

int main()
{
const char* constHello = "hello";
char mutableHello[] = "hello";
foo(constHello);
foo(mutableHello);
}

Это печатает:

const: привет
изменяемые: привет

Компилятор выберет наименьшую ограничительную перегрузку, какую только может. Так что если вы используете char* когда есть char* перегрузка, это тот, который он выберет; но если их нет, компилятор решит, что приведение к const char* является жизнеспособным преобразованием (обратное, очевидно, неверно).

Теперь очень просто, что все методы проходят this указатель как первый параметр любой функции. Этот параметр скрыт ради простоты. const в конце метода квалифицируется this аргумент. Поскольку, как мы только что видели, const для устранения перегрузок достаточно указателя, это будет эффективно работать.

1