Operator Overloading Varied Styles

Started by
7 comments, last by Nyarlath 15 years, 4 months ago
Hello everyone just a general question on different syntax on operator overloading and which are better in certain situations if indeed there is any difference. Ive only really been using operator overloads for 8 months and have come across a few different methods. The most popular doing something like this:

bool operator == (const MyClass &mc)
{
    return (variable == mc.variable); 
} 





and when discussing something on gamedev i remember a very helpful poster who said it helps to have 2 operator overloads of the same operator one including const which i think was written like this :

bool operator == (const MyClass &mc) const
{
    return (variable == mc.variable); 
} 





and sometimes like this:

const bool operator == (const myClass &mc) const //(which to me seems like it could just do with the const at the front or the beginning)
{
    return (variable == mc.variable); 
} 





and i found that the first method didnt work when i was working in VS 2005 at uni implementing a class that was later used in a list/vector/map that then used a find function from the algorithm header. Instead i think the third method was the only one that worked whereas here at home on vs 2008 it doesn't seem to be making a difference. The final method is the one being taught to us at university which although works in what seems all situations, i really don't like the syntax

friend bool operator < (const MyClass &lhs, const MyClass &rhs);

//with the body being defined else where e.g.

bool operator < (const MyClass &lhs, const MyClass &rhs)
{
	if (lhs.name != rhs.name)
		return (lhs.name < rhs.name);
	else
		return (lhs.ptype < rhs.ptype);
}





Is this actually the better way of doing it? or is there no real difference? I personally prefer the second method for comparison overloads as it never seems to give me any trouble. Also to me it seems like abuse of the friend operator to make the function global, which seems to me like bad practice. Then again ive never really thought the friend operator should be used unless really really necessary as to me it in certain situation it defeats the point of encapsulation, ive used a friend class once and 2bh there was probably a better way round that. However when i do assignments or multiplications the only method i've come across that i've used is:

const MyClass &operator=(const MyClass &myclass)
{
   variable = myclass.variable;
    return *this;    
}
//and
const MyClass &operator+(const MyClass &myclass) const
{
   return(MyClass ( variable + myclass.variable));   //with coresponding constructor 
}
//i remember trying something more like and having issues (but that was a while ago, maybe i was just being stupid)
const MyClass &operator+(const MyClass &MyClass ) const
{
variable += myclass.variable;   
return *this;   
}






i remember trying some other methods and having problems but i can't remember what they where and so have been sticking to the above. Any advice or pointers on the subject and points raised would be much appreciated, Thank you, Chris [Edited by - ChrisPepper1989 on November 25, 2008 3:53:39 PM]
Advertisement
Quote:Original post by ChrisPepper1989
bool operator == (const MyClass &mc) const

Correct. Not related to the function being an operator overload, though -- just to it being a member function that doesn't modify the object. clicky
Quote:const bool operator == (const myClass &mc) const

Returning const primitive values like this is meaningless. Whoever told you to do this, trust them less.
Quote:bool operator < (const MyClass &lhs, const MyClass &rhs)

Why do you dislike the syntax? Doesn't it make sense to you that the operands should be similar syntactically, rather than one being an implicitly declared pointer and the other an explicitly declared reference? BTW, there's often no need to make the operator a friend.
Thank you!

It was the friend part that made me dislike the syntax :)!

Although i do remember having issues with a similar syntax when it came to testing it with STL, but to be honest im starting to think the university computers are set up stupidly! As i've noticed a lot of weird errors on their machines.

As for the const bool, it was in a games programming book i have by Kevin Hawkins and Dave Astle, so i am kind of worried now :(!

Im asuming the const is still valid for the case of:
const MyClass &operator+(const MyClass &MyClass ) {variable += myclass.variable;   return *this;   }

as its not returning a primitive.

Thank you very much for clearing that up, any ideas on why i might have had problems with STL and <algorithm> in the past when it comes to syntax on overloading the < operator? which i did the same as the first example? Only on machines at university though that have 2005, don't see why this would make a difference? Unless it was a problem in the standard template library that was fixed before VS 2008
p.s. Thank you for the link its explaining alot
Something related that you should be aware of is Koenig Lookup (google it) -- it defines the rules for how symbols (ie - function and operator identifiers) are looked up in relation to a used object and its surrounding namespace -- which often applies to operators and other "utility" functions designed to work with a class but defined externally to it -- in other words things that you might have been tempted to friend.

Its hard to say without knowing more, but something like that may have been at the root of the problem you had at University on VS2005 vs no problems at home on VS2008 -- then again, the fact that it works on 2008 is just as likely due to improved template support... at any rate, its good to know and can explain wierdities like this. The good part is that you only really need to be aware of it -- as long as you use good namespacing practices you don't have much of anything left to worry about.

You're right to be wary of the friend keyword -- It expresses one of the strongest, I think the strongest, relationship that can be expressed in C++. As a general rule, you should strive to get results using the simplest and weakest tool that does the job as this promotes good code. You should only move to a stronger tool when you have exhausted the weaker ones.

throw table_exception("(? ???)? ? ???");

Quote:Original post by ChrisPepper1989
any ideas on why i might have had problems with STL and <algorithm> in the past when it comes to syntax on overloading the < operator?

Not in the slightest. There aren't any bugs in the 2005 STL implementation that I'm aware of. Error messages would help diagnose the problem.
To Ravyne: - Thanks that i found a page on Wikipedia that went over the overview and its interesting to know why STL can produce such horrible errors so easily

To Sneftel: - I'll recreate the error at Uni at some point soon and get all the information again. But from memory the linker complained that there was an unresolved external symbol, basically the usual message you get when calling a function that isn't defined and double clicking on it took me to a STL header, it was algorithm or at least something with in it and there was a function using the < operator in a pretty standard way if(something < something) (can't remember exactly what it was doing though). Even though i had written one using the none const standard, when i suffixed it with const it started working. Either that or the friend function mentioned bellow.

Thank you both for your useful resources and clearing up things that i needed to know! it is much appreciated! :)
Quote:Original post by ChrisPepper1989
and when discussing something on gamedev i remember a very helpful poster who said it helps to have 2 operator overloads of the same operator one including const which i think was written like this


There is only value in having both a const and non-const version of a member if you need both one that modifies the instance and one that doesn't. Since operator==() is highly unlikely to modify the object, the non-const version is redundant.

A common case when you need both versions would be for an operator[] on a class that provides array-like indexing:

class Array{private:    std::vector<int> data;public:    int &operator[](int index){ return data[index]; }    int operator[](int index) const { return data[index]; }};


This means that on a const Array, you can still use the [] method, but you just can't modify the array's contents. On a non-const Array, [] can give you read-write access.

This is just one example and as Sneftel said, it is not really specifically related to operator overloads.
Quote:Original post by ChrisPepper1989
const MyClass &operator+(const MyClass &MyClass )
{
variable += myclass.variable;
return *this;
}

Don't confuse + with += ! Here the statement without assignment operator involved "class1 + class2;" modify class1!

+= should return non-const, so that you can do "(class1 += class2) += class3;" to avoid temp variables, as for std::string (but don't do it! ;)
The only intuitive implementation of + returns a new object.

MyClass &operator+=(const MyClass &myclass) {  variable += myclass.variable;     return *this;   }MyClass operator+(const MyClass &myclass) const{  MyClass c(*this);  c += myclass;     return c;   }

This topic is closed to new replies.

Advertisement