2014-02-04 4 views
14

Для образовательных целей я хочу перегрузить и использовать оператор + = в каскаде.+ = перегрузка оператора и каскадирование?

class a { 
    public: 
     a(); 
     a& operator+= (float f); 
    private: 
     float aa; 
} 

a() { 
    aa = 0; 
} 

a& operator+= (float f) { 
    aa += f; 
    return *this; 
} 

a b; 
b += 1.0; // Works. 
b += 1.0 += 1.0; // Error : Expression must be a modifiable lvalue. 

Я не понимаю, почему выше не работает (в стороне от возможных ошибок синтаксиса - не пытался скомпилировать этот пример кода). Возвращая * это в перегруженном операторе + = метод, я бы ожидал, что второй + = 1.0 будет вызван на объект b, нет?

Спасибо.

+1

Вы должны размещать код без лишних «забавными» ошибок, которые не связаны с проблемой, которую вы пытаетесь показать. – juanchopanza

+0

Честно говоря, я всегда делал что-то вроде b + = 1.0 + 2.0; – IssamTP

+0

[Приоритет оператора] (http://en.cppreference.com/w/cpp/language/operator_precedence). '+ =' оценивается справа налево. – Nabla

ответ

26
b += 1.0 += 1.0; 

Ассоциативность для += является справа налево. Таким образом, вышесказанное интерпретируется как:

(b += (1.0 += 1.0)); 

Это имеет смысл? NO.

Для того, чтобы заставить его работать, вы должны написать:

(b += 1.0) += 1.0; 

Надежда, что помогает.

+4

* Facepalm *, спасибо! Хорошего дня. – user3020233

1

Пожалуйста, обратите внимание, что для того, чтобы иметь class a с наименьшим количеством сюрприз для своих пользователей, это, вероятно, лучше, чтобы также определить функцию-член

a& operator+=(a const&); 

, а также функции, не являющимися членами

a operator+(a const&, a const&); 
a operator+(a const&, float); 
a operator+(float, a const&); 

, которые определены в терминах одного из элементов operator+= перегрузки. Тогда вы можете написать

a1 += b1 + c1; 

где a1 имеет тип a переменные b1, c1 оба могут быть либо float или a. См. this question от для более подробной информации.

+0

'a operator + (a, a const &); 'лучше, чем' const & 'версия, не так ли? – Nawaz

+0

@Nawaz Конечно, но я надеялся избежать всего бизнеса эффективности и обсуждения lvalue/rvalue здесь, так как вы могли бы также иметь 2 перегрузки для 'operator + =' и 4 перегрузки 'operator +' со всеми комбинациями 'a &&' и 'a const &'. См. https://github.com/d-frey/operators То, что я делаю здесь, состоит в том, что для «делать то, что нужно делать» требуется, по крайней мере, несколько перегрузок 'a' и' float', а также 'operator +' идти по единственному 'operator + ='. – TemplateRex

+0

Достаточно справедливо :-) – Nawaz

0

Просто добавьте ответы, которые вы получили. Вам может быть интересно преобразовать конструкторы и/или операторы преобразования. Например:

class a { 
    public: 
     a(); 
     a(float f); 
     a& operator+= (float f); 
     operator float() const; 
    private: 
     float aa; 
}; 

a::a() { 
    aa = 0; 
} 

a::a(float f) { 
    aa = f; 
} 

a& a::operator+= (float f) { 
    aa += f; 
    return *this; 
} 

a::operator float() const { 
    return aa; 
} 

int main() 
{ 
    a b = 1.0; 
    b += 1.0; // Works. 
    b += (a)1.0 += 1.0; // Works. 
} 

или, может быть, лучше без оператора преобразования, но с operator+=(const a&);

class a { 
    public: 
     a(); 
     a(float f); 
     a& operator+= (float f); 
     a& operator+= (const a & x); 
    private: 
     float aa; 
}; 

a::a() { 
    aa = 0; 
} 

a::a(float f) { 
    aa = f; 
} 

a& a::operator+= (float f) { 
    aa += f; 
    return *this; 
} 

a& a::operator+= (const a & x) { 
    aa += x.aa; 
    return *this; 
} 

int main() 
{ 
    a b = 1.0; 
    b += 1.0; // Works. 
    b += (a)1.0 += 1.0; // Works. 
} 
Смежные вопросы