Как работает перегрузка функций const и non-const?
В stl полно таких определений:
iterator begin ();
const_iterator begin () const;
Поскольку возвращаемое значение не участвует в разрешении перегрузки, единственная разница здесь - это функция const
. Является ли эта часть механизма перегрузки? Что такое алгоритм компилятора для решения такой строки, как:
vector<int>::const_iterator it = myvector.begin();
Ответы
Ответ 1
В примере, который вы указали:
vector<int>::const_iterator it = myvector.begin();
Если myvector
не const, будет вызываться неконстантная версия begin()
, и вы будете полагаться на неявное преобразование из итератора в const_iterator.
Ответ 2
Компилятор "алгоритм" выглядит так:
Каждая функция-член класса X имеет неявный аргумент типа X & (Я знаю, большинство думают, что это X *, но стандартное состояние, что для целей перегрузки разрешено считать это ссылкой). Для const-функций тип аргумента - const X &. Таким образом, алгоритм, если функция-член называется двумя версиями, const и non-const, являются жизнеспособными кандидатами, и наилучшее соответствие выбирается так же, как и в других случаях разрешения перегрузки. Нет магии:)
Ответ 3
Да, модификатор const
влияет на перегрузку. Если myvector
const
в этой точке const
будет вызываться версия:
void stuff( const vector<int>& myvector )
{
vector<int>::const_iterator it = myvector.begin(); //const version will be called
}
vector<int> myvector;
vector<int>::const_iterator it = myvector.begin(); //non-const version will be called
Ответ 4
Из стандарта С++ (§13.3.1 Функции кандидата и списки аргументов):
For non-static member functions, the type of the implicit object parameter is "reference to cv X" where X is the class of which the function is a member and cv is the cv-qualification on the member function declaration. [Example: for a const member function of class X, the extra parameter is assumed to have type "reference to const X". ]
Итак, в вашем случае, если myvector
object is const
, компилятор выберет версию begin
, у которой есть неявный объектный параметр типа reference to const vector
, который является версией const begin
.
Ответ 5
Следует упомянуть, что С++ допускает перегрузку методов/функций const (например, foo() const), но перегрузка не const (например, bar (int a) и bar (const int a)).
Ответ 6
Компилятор определяет, является ли переменная объекта const или не во время компиляции
Затем он выбирает соответствующую перегрузку и любой возвращаемый тип.
class C {
public:
int f() { return 1; }
float f() const { return 1.5; }
};
// Non const.
C c;
assert(c.f() == 1);
// Convert variable const at compile time.
assert(const_cast<const C&>(c).f() == 1.5);
// Same as above but with an explicit reference.
const C& d = c;
assert(d.f() == 1.5);
// Analogous but with a new const object from the start.
const C e;
assert(d.f() == 1.5);