I am trying to preform operator overloading in C++;
for some reason the compiles keeps on giving me the error
error: ‘bool Matrix::operator==(const Matrix&, const Matrix&)’ must take exactly one argument
Now, I know that there is some way to to it with one argument using this, but I understood that by using friend I can do it this way, but it still is not working.
Here is my code,
Thanks in advance.
class Matrix{
public:
Matrix();
friend bool operator==(Matrix &mtrx1,Matrix &mtrx2);
friend bool operator!=(Matrix &mtrx1,Matrix &mtrx2);
protected:
std::vector<Cell> _matrix;
int _row;
int _col;
};
inline bool Matrix::operator==(const Matrix& mtrx1, const Matrix& mtrx2){
/* .......... */
}
The operator== member function is declared as:
class foo {
public:
bool operator==( foo const & rhs ) const;
};
The operator== global function is declared as:
bool operator==( foo const & lhs, foo const & rhs );
Generally, the member function is declared and defined first. Then, the global function is defined in terms of the member function as
Only one between the member function and global function is declared and defined. Having both of them is ambiguous for statements like (1) in the following
foo f1;
foo f2;
bool f1EqualsF2 = (f1 == f2 ); // (1), ambiguous
and in such cases compiler returns error. In g++, the error message looks like
equals.cpp:24: error: ambiguous overload for ‘operator==’ in ‘f1 == f2’
equals.cpp:8: note: candidates are: bool foo::operator==(const foo&) const
equals.cpp:17: note: bool operator==(const foo&, const foo&)
Whenever operator== is done, its recommended to do the corresponding operator!=.
Although you've put the friend declaration inside the class, it's not a member. So the function definition should be a non-member:
inline bool operator==(const Matrix& mtrx1, const Matrix& mtrx2) {...}
You also need to add const qualifiers to the arguments of the declarations, to match those in the definition.
class Matrix{
public:
Matrix();
friend bool operator==(const Matrix &mtrx1, const Matrix &mtrx2);
friend bool operator!=(const Matrix &mtrx1, const Matrix &mtrx2);
protected:
std::vector<Cell> _matrix;
int _row;
int _col;
};
inline bool operator==(const Matrix& mtrx1, const Matrix& mtrx2){
/* .......... */
return true;
}
Pass compilation in Visual Studio 2005.
omit the const qualifier in your friend declaration
don't need Matrix:: in operation== definition
You do it with 2 parameters if you are doing it outside of the class, not as a member function.
As a member function you need only 1 parameter (the other parameter is *this)
Related
I have the following class, it is defined like so:
namespace ns{
class Bit{
public:
explicit Bit(bool bit);
Bit() = default;
explicit operator bool () const;
[[nodiscard]]
bool value() const;
[[nodiscard]]
Bit operator==(const Bit& rhs) const;
//friend Bit operator==(const Bit &lhs, const Bit &rhs); also doesn't work
private:
bool m_bit;
};
//doesn't work
//[[nodiscard]]
//Bit operator==(const Bit &lhs, const Bit &rhs);
}
When I define the operator == overload as a standalone function, it doesn't work, I get
undefined reference to `ns::operator==(ns::Bit const&, ns::Bit const&)'
Similar story for the friend function version.
The definition of the standalone function is as follows in the .cpp file:
ns::Bit operator==(const ns::Bit &lhs, const ns::Bit &rhs) {
return ns::Bit(lhs.value() == rhs.value());
}
The definition of the member function, which works, is as follows
ns::Bit ns::Bit::operator==(const ns::Bit &rhs) const{
return Bit(value() == rhs.value());
}
Why am I being forced to make a member function?
ns::Bit ns::operator==(const ns::Bit &lhs, const ns::Bit &rhs) {
return ns::Bit(lhs.value() == rhs.value());
}
you prototyped ns::operator== then defined ::operator==.
Only ns::operator== is found via ADL. ::operator== may also be found depending on what other == operators and what namespace you are in, adding confusion.
Why does the following code
class Foo {
public:
bool std::operator==(const Foo&, const Foo&);
};
comes up as an error ' qualifier must be a base class of "Foo" '
I get a different (maybe more reasonable) error message here:
main.cpp:4:48: error: invalid use of '::'
bool std::operator==(const Foo&, const Foo&);
^
You cannot arbitrarily overload binary operator function as class member operator functions (see Operator Overloading).
You cannot do this referencing the std namespace
What you probably wanted is
class Foo {
public:
bool operator==(const Foo&) const;
};
If you're really sure you want to overload this in the std:: namespace, you can write:
namespace std {
bool operator==(const Foo& op1, const Foo& op2) {
return op1.operator==(op2);
}
}
or simply overload the binary operator==() function in the global namespace:
bool operator==(const Foo& op1, const Foo& op2) {
return op1.operator==(op2);
}
In-class binary operators have an implicit Foo const & as the left-hand side. Thus, you should only include one Foo const & as a parameter, not two.
edit: also, as mentioned in the other answer, you would have to drop the std:: in this case too.
Suppose I have the following class:
class Point{
private:
int x,y;
public:
int get_x() const {return x;}
int get_y() const {return y;}
Point() :x(0),y(0){}
Point(int x,int y):x(x),y(y){}
Point(const Point& P){
x = P.get_x();
y = P.get_y();
}
Point& operator= (const Point& P) {
x = P.get_x();
y = P.get_y();
return *this;
}
friend ostream& operator<<(ostream& os,const Point& P) {
os<<"["<<P.get_x()<<", "<<P.get_y()<<"]";
return os;
}
Point operator - (const Point &P){
return Point(x-P.get_x(),y-P.get_y());
}
friend bool operator > (const Point &A, const Point &B) {
return A.get_y()>B.get_y();
}
};
Here I used friend function. I can also use function without friend:
class Point{
...
bool operator > (const Point &B) const {
return y>B.get_y();
}
...
};
What are the differences between them in actual implementations? Also in the second method, the code won't compile without 'cont', why is that? Even after I changed the getter function into non-const function, it still won't compile without the 'const'.
As you've already noticed, comparison operator overloads can either be implemented as a member function or as a non-member function.
As a rule of thumb you should implement them as a non-member non-friend function where possible, as this increases encapsulation, and it allows (non-explicit) conversion constructors to be used on either side of the operator.
Say for instance your Point class for whatever reason had an int conversion constructor:
Point(int x);
With a non-member comparison operator you can now do the following:
Point p;
p < 3; // this will work with both a member and non-member comparison
3 < p; // this will **only** work if the comparison is a non-member function
You also seem to be confused about when to use const, again as a rule of thumb for comparison operators you should always use const wherever possible, because comparisons logically do not involve any change to the object.
As Point is a very small class you could also take it by value instead, so in order of most to least preferable your options are:
// Non-member, non-friend
bool operator>(Point const& A, Point const& B);
bool operator>(Point A, Point B);
// Non-member, friend
friend bool operator>(Point const& A, Point const& B);
friend bool operator>(Point A, Point B);
// Member
bool Point::operator>(Point const& B) const;
bool Point::operator>(Point B) const;
I'm trying to create a set that can be filled with instances of a class. I thought that a requirement for a set is that elements can be compared, and thus in this case I need to tell my class how they can be compared. I created the following class:
class Myclass
{
public:
Myclass(int i):storedval(i) {}
int getval(){return storedval;}
friend bool operator> (Myclass &first, Myclass &second)
{
return first.getval()>second.getval();
}
friend bool operator< (Myclass &first, Myclass &second)
{
return first.getval()<second.getval();
}
private:
int storedval;
};
But when I try to add instances to a set like this:
Myclass a(50);
set<Myclass> Bunchofclasses;
Bunchofclasses.insert(a);
It gives me a bunch of error text that I think tells me it doesn't understand the > and < operators. How should this be done properly?
You need to pass const references to the comparison function because it should not be allowed to modify the items being compared:
friend bool operator< (const Myclass& first, const Myclass& second)
{ // ^^^^^ ^^^^^
return first.getval() < second.getval();
}
This will require that you make getVal() const as well. This makes it callable on const instances or via const references:
int getval() const {return storedval;}
// ^^^^^
Note that you do not need operator> for the set to work. Less-than is enough.
Strictly speaking, you do not need a friend function here, since you are calling public member functions. The only thing that friend brings here is to allow you to declare a non-member function inside of the class definition.
Elements of a set are immutable, so the set needs to be able to compare const values. So the comparison needs to be:
friend bool operator< (Myclass const &first, Myclass const &second)
// ^^^^^ ^^^^^
(You should probably also do this with operator> and any other non-mutating operations you provide; but set only needs operator<).
Also, in order to access the value of a const object, the accessor also needs to be const:
int getval() const
// ^^^^^
I'm confused about friend operator overloading. It has no problem if I write the friend operator overloading function within the header file, but it gives me the following errors once I moved the function to class file. I googled some samples and they all written the function in the header file. What did I do wrong? Thanks.
...: error: expected ‘,’ or ‘...’ before ‘&’ token
...: error: ISO C++ forbids declaration of ‘statisticain’ with no type
...: error: ‘main_savitch_2C::statistician operator+(int)’ must have an argument of class or enumerated type
// a.h
class A
{
public:
friend A operator + (const A &a1, const A &a2);
};
// a.cpp
#include "a.h"
A operator + (const A &a1, const A &a2)
{
//
}
From the error message you're getting:
ISO C++ forbids declaration of ‘statisticain’ with no type
I think that you misspelled "statistician" by reversing the last two letters (note that you have "statisticain" instead of "statistician.")
This should have nothing to do with whether operator+ is implemented in the header or the .cpp file.
I agree with the previous answer. Also, if I may ask, why make the function a friend when both arguments and the return type are of the same class? why not make it a member so the first argument is passed implicitly by the this operator?
Move the two param version out of the class declaration. Or just use one param and the this pointer.
Here's an abbreviated real world example.
//complexnumber.h
class ComplexNumber
{
float _r;
float _i;
friend ComplexNumber operator+(const ComplexNumber&, const ComplexNumber&);
public:
ComplexNumber(float real, float img):_r(real),_i(img) {}
ComplexNumber& operator + (const ComplexNumber &other);
};
ComplexNumber operator+(const ComplexNumber &c1, const ComplexNumber& c2);
//complexnumber.h
ComplexNumber operator+(const ComplexNumber &c1, const ComplexNumber& c2)
{
return ComplexNumber(c1._r+c2._r, c1._i+c2._i);
}
// static
ComplexNumber& ComplexNumber::operator + (const ComplexNumber &other)
{
this->_r = this->_r + other._r;
this->_i = this->_i + other._i;
return *this;
}