Subscribe to Stuck in an Infiniteloop        RSS Feed
-----

Overloading Operators in C++

Icon 4 Comments
One neat thing you can do in C++ that is not present in Java is the ability to overload operators like * / + - % ^ & | ! , = < > <= >= ++ -- << >> == != && || *= /= %= ^= &= |= += -= <<= >>= -> ->* [] () new delete.

Here, I'll go over a few common ones: =, +. Why only addition you ask? Because one you understand one arithmetic operator, you understand them all (just change the operator :P )

This example was inspired from this thread.


Before we get too ahead of ourselves, the purpose of overloading an operator is to allow the user/programmer to have statements such as:

objectOne = objectTwo;
objectOne = objectTwo / objectThree;
//so on and so forth



Without overloading these operators the compiler will not only complain, but any work around could be cumbersome and ultimately frivolous. Having that said, our class:

class JarType {
private:
	int numUnits;
public:
	JarType()				{ numUnits = 0; };
	JarType(int n)			{ numUnits = n; };
	int getUnits()			{ return numUnits;};
};



Not overly complicated, which is good for our purposes. Notice that we have a default constructor and an additional one that takes an integer as a parameter. There's s only one data member numUnits, an integer. We have an accessor function since we want to keep the data private. Now with this class definition the following code will not work:

int main()
{
	JarType jarOne, jarTwo(10), jarThree(15);
	jarOne = jarTwo;
	cout << jarOne.getUnits()		<< endl; //assignment operator jarOne.numUnits now equals 10
	jarOne = (jarTwo + jarThree);
	cout << jarOne.getUnits()		<< endl; // addition operator jarOne.numUnits now equals 25
	return 0;
}



The compiler will complain at you about nearly every line of that code. Mainly because it does not know how to react to setting one JarType to another or how to assign a JarType to the addition of two other JarTypes. So, lets talk about how to solve this:

JarType operator +(const JarType& secondJar) 
{
		JarType temp;
		temp.numUnits = numUnits + secondJar.numUnits;
		return temp;
}



The function will return an object of this class, the parameter is what comes to the right of the '+' sign. Often it will be called rhs for "right hand side". We declare a temporary variable (aptly named) and then assign its data member to the addition of the left hand side's numUnits (simply written as numUnits, in java one would write this.numUnits, same principle) and the right hand side (the parameter)'s numUnits. We then return the temp. The left hand side operator's numUnits will now be equal to temp's. Temp goes out of scope so we don't need to worry about cleaning it up, it was declared on the stack, You might be asking, why don't we just declare this void and simply add the two term? Well, what if we want to add two objects and then assign the result to another object without permanently modifying the added objects? See below:

void operator =(const JarType& secondJar)
{
		numUnits = secondJar.numUnits; //assign data member from one to another
}



Overloading equals will assign the private data from the parameter (right hand side) to the left hand side. Alternately we could return a JarType for this, but then we'd have to get into copy constructors and that goes a little out of the scope of this single blog post (perhaps more on that later). Notice in each example that the parameter is declared const. That is to ensure that the data cannot be accidentally or inadvertently modified. We are protecting ourselves from ourselves.

Happy Coding!

--KYA


For further reading: See here

4 Comments On This Entry

Page 1 of 1

bszmyd 

17 February 2009 - 08:19 PM
Don't write commutative operators as a member function to classes when the argument can be of a different type. The reason is simple:
Foo {
   Foo ( int );
   Foo operator+( int const ) const;
   // ...
};

Foo b(2);
Foo good = b + 5; // This works.
Foo bad = 5 + b; // This doesn't.

The reason is that with b + 5 the compiler looks for a function like:
b.operator+(int const)

Which it finds. However with 5 + b the compiler looks for a function matching:
5.operator+( Foo const& )

Which it will never find. If you however declare it as a non member function like so:

Foo operator+( Foo const&, Foo const& );
Then 5 + b will compile because the compiler can implicitly convert 5 into a Foo and then make the above call. You can make that one function work for any type as long as there is a constructor for Foo that takes that type (in this case long).

Don't forget to make it a friend or use the getters/setters in its implementation!
0

KYA 

17 February 2009 - 08:22 PM
Thanks for pointing that out. I didn't plan (in this implementation) to have objects add constants, the idea was to only have two objects add to one another.

And yes, setters and getters would be optimal, but for a brief, down and dirty run, using bare data members is ok.
0

bszmyd 

17 February 2009 - 08:24 PM

KYA, on 17 Feb, 2009 - 07:22 PM, said:

And yes, setters and getters would be optimal, but for a brief, down and dirty run, using bare data members is ok.

I think so too, just know that it won't work as a non-member function in my approach and I hate keeping track of who's friends with who :)
0

KYA 

17 February 2009 - 08:25 PM
It's just as irritating as in real life :P
0
Page 1 of 1

January 2022

S M T W T F S
      1
2345678
9101112131415
161718192021 22
23242526272829
3031     

Tags

    Recent Entries

    Recent Comments

    Search My Blog

    19 user(s) viewing

    19 Guests
    0 member(s)
    0 anonymous member(s)