нуб здесь. Ниже приведен фрагмент определения класса, с которым я столкнулся в примере с книгой:
double& operator[](int i);
double operator[](int i) const;
Мой вопрос: почему это не двусмысленно? При компиляции файлов проекта компилятор не выдает никакой ошибки.
Кроме того, в следующем (представьте, что AnyClass содержит valarray<double>
объект, например, и я хочу получить к нему доступ напрямую):
AnyClass test;
cout << test[2]
какую версию использует компилятор?
Это не двусмысленно, потому что const
является частью подписи и может использоваться для разрешения перегрузки. Так что если вы используете operator[]
на неконстантном объекте он выбирает перегрузку без const
потому что это самый конкретный. И если вы используете его на const объекте, он выбирает перегрузку с const
потому что это единственный, который применяется.
Если вызвано на const
объект, const
версия будет использоваться, иначе другая.
Вот как компилятор разрешает неоднозначность.
AnyClass test;
const AnyClass const_test;
std::cout << test[2]; // calls operator[](int)
std::cout << const_test[2]; // calls operator[](int) const
Чтобы понять это, в основном вам просто нужно понять, что 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
для устранения перегрузок достаточно указателя, это будет эффективно работать.