Почему возвращение * этого результата в бесконечном цикле? - PullRequest
3 голосов
/ 04 января 2012
class binaryOperators 
{
    public:
        int i;

        binaryOperators (int tempI = 0)
        {
            i = tempI;
        }

        binaryOperators operator+ (const binaryOperators &right);
};

binaryOperators binaryOperators :: operator+ (const binaryOperators &right)
{
    return binaryOperators (*this + right.i);
}

binaryOperators operator+ (const binaryOperators &left, const binaryOperators &right)
{
    return binaryOperators (left.i + right.i);
}

int main ()
{
    binaryOperators obj (10);

    obj = 11 + obj;

    obj = obj + 11;

    return 0;
}

Итак, здесь оператор obj = 11 + obj; вызывает функцию с явной спецификацией аргумента. и этот obj = obj + 11; вызывает функцию, которая является членом класса. Хорошо.

Проблема в том, что второй вызов приводит к бесконечному циклу. Каковы причины и как этого избежать?

Ответы [ 2 ]

9 голосов
/ 04 января 2012

Проблема в утверждении:

return binaryOperators (*this + right.i);

*this относится к типу binaryOperators, поэтому требуется оператор с левым аргументом типа (или ссылки на) binaryOperators.

Возможно, вы предоставляете два соответствующих оператора, поэтому правый аргумент должен иметь тип const binaryOperators &. Таким образом, right.i преобразуется во временные двоичные операторы с использованием соответствующего конструктора.

В результате оператор-член в конечном итоге вызывает себя, который вызывает себя, вызывает себя и т. Д., Что приводит к бесконечной рекурсии (то, что вы видите как бесконечный цикл).

Вероятно, вы можете исправить это, используя:

return binaryOperators (this->i + right.i);
5 голосов
/ 04 января 2012

Преобразование из binaryOperators::i (типа int) в binaryOperators неявно (то есть не объявлено explicit).

return binaryOperators (*this + right.i); // (1)
binaryOperators binaryOperators :: operator+ (const binaryOperators &right); // (2)
binaryOperators operator+ (const binaryOperators &left, const binaryOperators &right); // (3)

В строке (1) можно рассмотреть две функции operator+: версия участника (2) и бесплатная версия (3). Поскольку LHS относится к типу binaryOperators&, версия участника применима и предпочтительна. Его аргумент имеет тип const binaryOperators &, а аргумент, указанный в строке (1), имеет тип int, поэтому компилятор пытается преобразовать int в const binaryOperators &.

Поскольку существует не-explicit конструктор с одним аргументом, он используется как неявное преобразование из int в const binaryOperators &. Теперь у нас есть два операнда типов binaryOperators& и const binaryOperators &, можно вызвать operator+ в (2), и мы находимся именно там, где начали.

Урок: не переусердствуйте в неявных преобразованиях.

...