Solved

operator overload: incompatible type and too many params

Posted on 2016-10-27
5
40 Views
Last Modified: 2016-10-29
I'm trying to overload operators in C++11 in a simple class.  I have the following (partial) class defined:
//Board.h
public class Board {
public:
	Board();
	bool isEmpty(int,int);
	void setCell(int, int,bool);
	bool getCell(int, int);

	void operator= (const Board &b) {};
	inline bool operator==(const Board& lhs, const Board& rhs) {return false;};
}

//Board.cpp
void Board::operator= (const Board &b) {
	for (int r = 1; r <= ROWS; ++r) {
		for (int c = 1; c <= COLS; ++c) {
			b.isEmpty(r,c);
//			setCell(r, c, b.getCell(r,c));
		}
	}
};

Open in new window

Lines 9 & 10 (in Board.h) is where I'm encountering problems.  The line 10 function is inline, and empty currently, and the line 9 function (operator=) is below in Board.cpp.  For operator= I'm getting this error on line 17:
error C2662: 'bool Board::isEmpty(int,int)' : cannot convert 'this' pointer from 'const Board' to 'Board &'

Open in new window

I'm just calling the isEmpty function on the input Board, which doesn't modify anything.

With "operator==", I get the error:
error C2804: binary 'operator ==' has too many parameters

Open in new window

Operator== needs two parameters, right?  I got this code off a tutorial site and just changed the class from 'X' to 'Board'.

I feel like these two errors are related, though I tried compiling them separately and both failed.  What am I doing wrong?
Thanks!
0
Comment
Question by:ugeb
  • 2
  • 2
5 Comments
 
LVL 30

Accepted Solution

by:
Zoppo earned 300 total points
ID: 41862639
Hi ugeb,

first you call isEmpty (which is not declared as const) of the const instance b. To resolve this just declare and implement isEmpty as const, i.e.:
bool isEmpty(int,int) const;

Open in new window


Next: == operator as class member doesn't need two parameters, it only needs one parameter which in the function is compared with the this-instance. Beside this you can implement a global == operator outside of the class, in this case you need two parameters.

At last a hint: a = operator should always return a reference to this in order to allow statements like a=b=c; - i.e.:
...
Board& operator= (const Board &b);
...
Board& Board::operator= (const Board &b) {
	for (int r = 1; r <= ROWS; ++r) {
		for (int c = 1; c <= COLS; ++c) {
			b.isEmpty(r,c);
//			setCell(r, c, b.getCell(r,c));
		}
	}
	return *this;
};

Open in new window

Hope this helps,

ZOPPO
1
 
LVL 11

Author Comment

by:ugeb
ID: 41862967
Hi Zoppo,

Thank you for the clarification. I tried it and realized that I had to const not just the isEmpty function, but also functions that were called from isEmpty, even though they didn't have the board as their parameter!  Seems like I would have to do a const_cast to avoid that domino effect.

Thank you for the tip on returning the *this reference. I wonder, though, how you would treat operator+ then?  It would need to return a copy, not a reference.  If I then return a copy from a new operation, do I need to worry about memory leaks?
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 41863451
Hi again,

you should try to avoid removing const anywhere using a const_cast. A function which is called isEmpty shouldn't need to anyhow modify the object so declaring it const should be possible.

The rules for the const-ness are quite simple: You can only call functions which are declared as const with a const instance. From within a member function which is declared as const you can only call other member functions which are declared as const too.

It is highly recommended to declare functions as const which are not expected to modify the object. In you code IMO even getCell and == operator should be declared as const since from their names they're not expected to modify any members.

And about the return *this; as reference: AFAIK it would even be possible to return *this when the return value is not declared to be a reference, I think even then a=b=c should work, but in this case i.e. b=c will create a copy (when the operator == returns an instance) using the copy constructor - now it's often the case copy constructors are implemented in a way they simply call the assignment operator, so this would lead to infinite loops. With operator + this is not a problem so returning the result by value is ok, memory leaks should be avoided in copy constructor and/or assignment operator.

ZOPPO
1
 
LVL 32

Assisted Solution

by:sarabande
sarabande earned 200 total points
ID: 41863682
you can implement a global == operator outside of the class, in this case you need two parameters.
fyi, you also could define a 'friend' global operator== with two arguments within the class. this has the Advantage that the members of the class can be accessed without getters.

class Board
{
     ...
     friend Board & operator==(const Board & b1, const Board & b2)
     {
            ...
            return *this;
     };
};

Open in new window


I would have to do a const_cast to avoid that domino effect
as the usage of const is an optional thing you were doing to have safer code, using a const_cast is a kind of betraying yourself and it is always a miserable design. as Zoppo has told, nobody would expect that calling IsEmpty() function would modifiy the object. from a designer's view IsEmpty neither should have arguments. you were passing two integers to Board::IsEmpty? does that mean the IsEmpty checks the two arguments whether they were "empty". if so, why it is a member of class Board?


I wonder, though, how you would treat operator+ then?  It would need to return a copy, not a reference.  If I then return a copy from a new operation, do I need to worry about memory leaks?
the operator+=  would also return *this, same as operator=. the operator+ would not, even if you could do it. return *this in operator+ actually is a severe design error. operator+ should be const and definitively need to return the result by value.

if a function returns by value, the result is a tempory which is alive until the next block end }. you don't have to care for leaks. if you return *this you were returning a reference to an existing object which doesn't allocate any extra memory (and therefore never leaks). the greater risk with return values is that you were returning references or pointers of local objects. after the function call, the pointers are invalid and in most cases it would crash sooner or later.

Sara
1
 
LVL 11

Author Closing Comment

by:ugeb
ID: 41865435
Thank you both.  I've not used operator overloading much and so I'm having to learn it, and your comments are very useful.  Thanks again!
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now