2009-11-29 3 views
4

Я немного смущен, почему мне сказали вернуть const foo из двоичного оператора в C++ вместо простого foo.Корректность верности при перегрузке оператора C++ возвращает

Я читал «Мышление на C++» Брюса Эккеля, и в главе о перегрузке оператора он говорит, что «создавая возвращаемое значение [избыточного бинарного оператора] const, вы утверждаете, что только Функция const member может быть вызвана для этого возвращаемого значения. Это const-correct, потому что это мешает вам хранить потенциально ценную информацию в объекте, который, скорее всего, будет потерян ».

Однако, если у меня есть оператор плюс, который возвращает сопзЬ, и оператор инкремента префикс, этот код недействителен:

class Integer{ 
int i; 

public: 
    Integer(int ii): i(ii){ } 
    Integer(Integer&); 

    const Integer operator+(); 
    Integer operator++(); 
}; 


int main(){ 

Integer a(0); 
Integer b(1); 

Integer c(++(a + b)); 
} 

Чтобы разрешить такого рода уступки, не имеет смысла, чтобы иметь + возвращает неконстантное значение? Это можно сделать, добавив const_casts, но это становится довольно громоздким, не так ли?

Спасибо!

ответ

4

Когда вы говорите ++ х, вы говорите «добавьте 1 в x, сохраните результат обратно в x и скажите мне, что это такое». Это оператор preincrement. Но, в ++ (a + b), как вы должны «вернуть результат обратно в + b»?

Конечно, вы можете сохранить результат обратно во временное, которое в настоящее время удерживает результат + b, который скоро исчезнет. Но если вам все равно, где был сохранен результат, почему вы увеличили его, а не просто добавили?

0

Копировальные конструкции обычно принимают const ссылка, решая эту проблему для вас.

(Имея неконстантную копию CTOR подразумевает некоторую передачу ресурсов, которые могут быть полезны иногда, но для 99% всех ситуаций, это не требуется)

4

FYI, ++(a + b) является незаконным даже с POD (простые старые типы данных, такие как int). Поэтому имеет смысл не допускать его для ваших собственных типов классов. Попробуйте следующее:

int a = 1; 
int b = 2; 
int c = ++(a+b); 

GCC возвращается error: lvalue required as increment operand.

В вашем случае, было бы предпочтительнее, чтобы ваш конструктор копирования принять const Integer аргумент, и создать свой Integer c, как это вместо:

Integer c(a + b + Integer(1)); 
0

Я считаю, что пример OP был бы пригоден к вопросу, если оператор сложения заменяются любым другим бинарным оператором, который возвращает ссылку, например, оператор присваивания:

Integer c(++(a = b)); 

Я пришел сюда, интересно, должен ли я сделать мой оператор присваивания возвращает константный или неконстантная ссылка. Some tutorials используют неконстантные версии, вопреки совету «Мышление в C++». И some other references дают основания для этого:

Обратите внимание, что возвращенная ссылка не объявлена ​​как const.Это может быть немного запутанным, потому что это позволяет вам писать такие сумасшедшие вещи, как это:

MyClass a, b, c;

...

(a = b) = c; // Какие??

На первый взгляд вы можете предотвратить ситуации, подобные этому, имея оператор = вернуть ссылку на константу. Однако такие утверждения будут работать с примитивными типами. И, что еще хуже, некоторые инструменты действительно полагаются на это поведение. Поэтому важно вернуть неконстантную ссылку из вашего оператора =. Эмпирическое правило: «Если он достаточно хорош для int, он достаточно хорош для пользовательских типов данных».

Смежные вопросы