Перегрузка неконстантной ссылочной функции С++

В следующем коде:

int foo(const int& f) //version 1
{
    int g = f;
    return int(foo(g)); // calls itself, turning into SO
}

int& foo(int& f) //version 2
{
    f *= -1;
    return f;
}

int main()
{
    int f = 11;
    cout << foo(f) << endl;
    cout << foo(22) << endl;
}

Первый cout выводит -11, как и ожидалось; f — это lvalue, поэтому он привязывается ко второй версии foo (хотя он может быть привязан и к 1-й версии, вторая версия лучше подходит).

Второй вызов foo использует rvalue в качестве параметра, поэтому единственной жизнеспособной версией foo является первая. Все идет нормально. Внутри первой версии foo я сделал копию параметра, чтобы можно было вызывать вторую версию (с lvalue) и возвращать ее копию после вызова второй версии foo. Дело в том, что это приведет к переполнению стека; все равно первая версия foo будет называться.

Может кто-нибудь объяснить мне, почему это происходит? Я ожидаю, что g внутри первой версии foo привяжется ко второй версии foo при передаче в качестве параметра.


person user1019710    schedule 26.11.2013    source источник
comment
Как первый foo узнает о втором foo?   -  person K-ballo    schedule 26.11.2013


Ответы (3)


Это действительно просто - foo в этот момент означает только foo(const int& f). Второго выбора нет. Еще нет. Поменяйте определения. Или разделить их:

int foo(const int& f);
int& foo(int& f);

int main()
{
    int f = 11;
    cout << foo(f) << endl;
    cout << foo(22) << endl;
}


int foo(const int& f) //version 1
{
    int g = f;
    return int(foo(g)); // calls itself, turning into SO
}

int& foo(int& f) //version 2
{
    f *= -1;
    return f;
}
person Luchian Grigore    schedule 26.11.2013

Первое объявление foo не знает о существовании второго. Попробуй это:

int foo(int& f);
int foo(const int& f) //version 1
{
    int g = f;
    return int(foo(g)); // calls itself, turning into SO
}
person Raxvan    schedule 26.11.2013

Когда компилятор достигает строки:

return int(foo(g))

Он не знает о вашей перегруженной версии 2. Добавьте объявления прототипа в начало файла:

int foo(const int& f);
int& foo(int& f);

Таким образом компилятор будет знать о существовании версии 2 и сможет учитывать ее при выборе foo для вызова.

person Sean    schedule 26.11.2013