views:

164

answers:

7

Just curious on why a param has to be a const in operation overloading

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

couldn't you have easily done something like this ??

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

Isn't when something becomes a const, it is unchangeable for the remainder of the applications life ?? How does this differ in operation overloading ???

+6  A: 

You don't need const:

@numerical25: Just curious on why a param has to be a const in operation overloading

It's not required, but it is a good design decision.

See the C++ standard Section 12.8-9:

A user-declared copy assignment operator X::operator= is a non-static non-template member function of class X with exactly one parameter of type X, X&, const X&, volatile X& or const volatile X&


I think it's a good idea though:

Using a const parameter does seems like a logical design decision to me though because you want to ensure that the other value will not be changed.

It tells other people that use your class that you will not be changing the other value when you say something like: myObject = other; and it enforces this so you can't accidentally change other.

Also if you allowed non const references to the object as the parameter, then you are limiting the amount of objects that can use your function. If it is const it can be used for parameters that are const and non const. If your parameter is non const it can only be used by parameters that are non const.


const only applies to the current reference, not the object:

@numerical25: Isn't when something becomes a const, it is unchangeable for the remainder of the applications life ?? How does this differ in operation overloading ???

A const reference is simply that a reference that is const. It does not change the const-ness of the actual object you are passing in.


An example of non-const operator overloading:

Here is an example of operator overloading where the parameter is not const.
I DO NOT RECOMMEND TO DO THIS THOUGH:

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;
}
Brian R. Bondy
And it's `const` for the scope of the declaration not the application life.
CuppM
@CuppM: Yes that is implied as the whole reference variable itself also goes out of scope. It doesn't change the const-ness of the original object during it's scope though. For example if you have 2 threads.
Brian R. Bondy
+2  A: 

A const parameter is const throughout the function using it, it does not change its constness outside of it.

In this case you want to declare a const argument so that your assignment operator accepts both non-const variables and const variables; the latter case, in particular, includes the result of expressions, which is a temporary const variable and which you generally want to support in assignments.

UncleZeiv
O, you are saying that g = (a+b*c) the result on the right side is considered a constant ?? When you say that a const is only a const within the function. Are you saying that once that function is done executing. Those values will be able to be changed again ??
numerical25
You know what. It does make sense now. If I cast a const value into a varible. that doesnt make the varible a const, it just means it now holds the value of the const which can be changable
numerical25
@numerical, keep in mind ur idea only works like what u mentioned if it is pass-by-reference.
YeenFei
+1  A: 

If you used

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

then did this:

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

You'll get an error because my_vector is a const CVector& and that can't be cast to a CVector& (non-const reference). It's just the local reference to it inside the operator= function that is const, not the entire object itself.

AshleysBrain
A: 

For the same reason you would use const anywhere: to ensure that future changes to the method don't inadvertently modify the passed in parameter, to help document the interface to notify callers that it is safe to pass param without risk of it changing, and to allow callers to pass in references that are declared as const in the calling code.

RickNotFred
+1  A: 

You can use the non-const variety, but this has two repercussions, one which is functional, and one which is about what you, as the writer of the function, are telling the user.

1) people calling the function that takes a non-const reference would not be able to call it using a const variable

2) when you have a function argument that's a non-const reference, you're signalling, "I reserver the right to change this". Typically, when a user of your function writes a = b;, he doesn't expect b to change.

Note that there's a third option you could use for this, pass-by-value:

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

This doesn't have either of the problems I mention above. However, it's very inefficient. Because of these three factors, passing by reference-to-const is preferred, especially in cases like a vector where copying can be expensive.

jwismar
A: 

Another reason is to allow for conversions. For example:

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

Here, an implementation might choose to only provide the assignment operator that takes a const reference to a string as a parameter, and depend on the compiler using a constructor to create a temporary string from the char * "bar". This would not work if the op='s parameter was not const, as you cannot bind a temporary to a non-const reference.

anon
A: 

The const qualifier makes the passed parameter (in your example it is 'const CVector& param') as read only. The const qualifier ensures that the parameter (param) is not altered inside the operator=() method.

Without the const qualifier, the following is possible:

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

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

  return *this;
}

The above method alters the right hand side operand 'param' after assigning the value to the left hand side operand. The const qualifier helps you not to violate the semantics of the assignment operation.

anand.arumug