почему вы должны предоставить ключевое слово const в перегрузках операторов - PullRequest
6 голосов
/ 01 июня 2010

Просто любопытно, почему param должен быть const в перегрузке операций

CVector& CVector::operator= (const CVector& param)
{
  x=param.x;
  y=param.y;
  return *this;
}

разве вы не могли бы легко сделать что-то подобное ??

CVector& CVector::operator= (CVector& param) //no const
{
  x=param.x;
  y=param.y;
  return *this;
}

Разве это не так?когда что-то становится const, оно остается неизменным на оставшуюся часть жизни приложения ??Чем это отличается при перегрузке работы ???

Ответы [ 7 ]

8 голосов
/ 01 июня 2010

Вам не нужно const:

@ numeric25: просто любопытно, почему параметр должен быть константой при перегрузке операции

Это не обязательно, но это хорошее дизайнерское решение.

См. Стандарт C ++, раздел 12.8-9:

Пользовательское назначение копирования оператор X :: operator = является нестатическим не шаблонная функция-член класса X с ровно одним параметром типа X, X &, const X &, летучий X & или const изменчивый X &


Я думаю, что это хорошая идея:

Использование параметра const кажется мне логичным решением при проектировании, поскольку вы хотите убедиться, что другое значение не будет изменено.

Он говорит другим людям, которые используют ваш класс, что вы не будете изменять значение other, когда говорите что-то вроде: myObject = other;, и это принудительно применяется, чтобы вы не могли случайно изменить other.

Также, если вы разрешили неконстантные ссылки на объект в качестве параметра, тогда вы ограничите количество объектов, которые могут использовать вашу функцию. Если это const, его можно использовать для параметров, которые являются постоянными и не постоянными. Если ваш параметр не является константным, он может использоваться только параметрами, которые не являются константными.


const применяется только к текущей ссылке, а не к объекту:

@ numeric25: разве когда что-то становится константой, оно остается неизменным до конца жизни приложения? Чем это отличается при перегрузке работы ???

Ссылка const - это просто ссылка const. Это не меняет постоянство фактического объекта, в котором вы передаете.


Пример неконстантной перегрузки оператора:

Вот пример перегрузки операторов, когда параметр не является константой.
Я НЕ РЕКОМЕНДУЮ ДЕЛАТЬ ЭТОТ МЫСЛЬ:

class B
{
public: 
 const B& operator=(B& other)
 {
  other.x = 3;
  x = other.x;
  return *this;
 }

 int x;
};


void main(int argc, char** argv[])
{
 B a;
 a.x = 33;
 B b;
 b.x = 44;
 a = b;//both a and b will be changed
 return 0;
}
2 голосов
/ 01 июня 2010

Параметр const является константным во всей функции, использующей его, он не меняет свою константность вне его.

В этом случае вы хотите объявить константный аргумент, чтобы ваш оператор присваивания принимал как неконстантные, так и константные переменные; последний случай, в частности, включает в себя результат выражений, который является временной переменной const и которую вы обычно хотите поддерживать в присваиваниях.

1 голос
/ 01 июня 2010

Вы можете использовать неконстантную разновидность, но это имеет два последствия, одно из которых функциональное, а другое о том, что вы, как создатель функции, говорите пользователю.

1) люди, вызывающие функцию, которая принимает неконстантную ссылку, не смогут вызвать ее с помощью константной переменной

2) когда у вас есть аргумент функции, который является неконстантной ссылкой, вы сигнализируете: «Я оставляю за собой право изменить это». Обычно, когда пользователь вашей функции пишет a = b;, он не ожидает, что b изменится.

Обратите внимание, что для этого можно использовать третий вариант передачи по значению:

CVector& CVector::operator= (CVector param) //no reference

Это не имеет ни одной из упомянутых выше проблем. Однако это очень неэффективно. Из-за этих трех факторов передача по ссылке на const является предпочтительной, особенно в случаях, таких как вектор, где копирование может быть дорогим.

1 голос
/ 01 июня 2010

Если вы использовали

CVector& CVector::operator= (CVector& param) // no const

затем сделал это:

const CVector& my_vector = GetMyVector();
some_other_vector = my_vector; // call assignment operator - error!

Вы получите ошибку, потому что my_vector - это const CVector&, и его нельзя привести к CVector& (неконстантная ссылка). Это просто локальная ссылка на нее внутри функции operator=, которая является константой, а не весь объект.

0 голосов
/ 02 июня 2010

Спецификатор const делает переданный параметр (в вашем примере это const CVector & param) доступным только для чтения. Спецификатор const гарантирует, что параметр (param) не изменяется внутри метода operator = ().

Без квалификатора const возможно следующее:

CVector& CVector::operator= (CVector& param)
{
  x=param.x;
  y=param.y;

  param.x = 10; // some random value
  param.y = 100;

  return *this;
}

Вышеуказанный метод изменяет правый операнд 'param' после присвоения значения левому операнду. Спецификатор const помогает вам не нарушать семантику операции присваивания.

0 голосов
/ 01 июня 2010

Другая причина заключается в разрешении конверсий. Например:

string s = "foo";
s = "bar";

Здесь реализация может предпочесть предоставить только оператор присваивания, который принимает константную ссылку на строку в качестве параметра и зависит от компилятора, использующего конструктор для создания временной строки из char * "bar". Это не будет работать, если параметр op = не является константным, поскольку вы не можете связать временную ссылку с неконстантной ссылкой.

0 голосов
/ 01 июня 2010

По той же причине вы должны использовать const где угодно: чтобы будущие изменения метода не изменяли непреднамеренно переданный параметр, чтобы помочь в документировании интерфейса для уведомления вызывающих абонентов, что безопасно передавать param без риска его возникновения изменение, и позволить вызывающим абонентам передавать ссылки, которые объявлены как const в вызывающем коде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...