Writing the implementation for an operator method - c++

So I have a LongInt class that will have new definition for the + and * operators. The initialization in the header file looks like:
friend LongInt operator+(const LongInt& x, const LongInt& y);
friend LongInt operator*(const LongInt& x, const LongInt& y);
however in my implementation file, where I'm defining the methods found in the header, VS doesn't recognize the operator+ function or the operator* function as being listed in the header. I'm using the code:
friend LongInt LongInt::operator+(const LongInt& x, const LongInt& y)
{
}
and
friend LongInt LongInt::operator*(const LongInt& x, const LongInt& y)
{
}
Any ideas as to why this code wont work when I'm trying to define the operators?

The friend keyword is only used when declaring or defining the operator inside of a class; when declaring the operator as a friend inside of the class and defining it elsewhere, friend is only used on the declaration, not the definition. Also, functions declared as friend inside a class are in fact free functions in namespace scope, not class members. So, your definitions should look more like:
LongInt operator +(LongInt const& x, LongInt const& y) { /*...*/ }
LongInt operator *(LongInt const& x, LongInt const& y) { /*...*/ }
For further reading material, read over the following page: C++ FAQ: Friends

You're overriding an operator ... you "call" it using the operator:
LongInt foo;
LongInt bar;
LongInt foobar = foo + bar;

Related

Overloading << operator in C++ requires friend

I'm learning C++ and specifically the operator overloading.
I have the following piece of code:
#include <iostream>
#include <string>
using namespace std;
class Vector2
{
private:
float x, y;
public:
Vector2(float x, float y)
: x(x), y(y) {}
Vector2 Add(const Vector2& other) const;
Vector2 operator+(const Vector2& other) const;
Vector2 operator*(const Vector2& other) const;
friend ostream& operator << (ostream& stream, const Vector2& other);
Vector2 Multiply(const Vector2& other) const;
};
ostream& operator << (ostream& stream, const Vector2& other)
{
stream << other.x << ", " << other.y;
return stream;
}
Vector2 Vector2::Add(const Vector2& other) const
{
return Vector2(x + other.x, y + other.y);
}
Vector2 Vector2::operator+(const Vector2& other) const
{
return Add(other);
}
Vector2 Vector2::Multiply(const Vector2& other) const
{
return Vector2(x * other.x, y * other.y);
}
Vector2 Vector2::operator*(const Vector2& other) const
{
return Multiply(other);
}
int main()
{
Vector2 position(4.0f, 4.0f);
Vector2 speed(0.5f, 1.5f);
Vector2 powerup(1.1f, 1.1f);
Vector2 result = position.Add(speed.Multiply(powerup));
Vector2 result2 = position + speed * powerup;
std::cout << result2 << std::endl;
std::cin.get();
}
Question: if I want this to work, I need to declare my ostream& operator << as friend. Otherwise MS Studio tells me: "Function definition for operator << not found"!
I don't understand why. I don't need to declare the other operators as friend, so why is this necessary in this case?
Thanks.
The operator<< must be defined as non-member function (as well as operator>>).
Let's take a look at the case when our class has defined the operator<< as a member function, we would have to do output like so:
// Member function, lhs is bound to implicit this
ostream& operator<<(ostream&) const;
Myclass obj;
obj << std::cout;
Why so? Because you know that an overloaded operator is just a function. So, underlying call to this function looks like this:
obj.operator<<(std::cout);
If the operator is a member function, there's no other way. Since we can't modify the library.
So, in order for the operator to access private data members, i.e. the x and y, we have to declare it as a friend.
The arithmetic operators ordinarily should also be non-member functions, to allow conversions for either of the operands. Thought it is not required. These also should not change state of their operands and should produce a new value, which also stimulates to approach them from non-member function.
Also, I would advise you to get rid of the using namespace std and specify namespaces explicitly (or at least avoid mixing up).
Operators + and * are declared as member functions of Vector2, so they are naturally able to access private members of Vector2.
However, you can't declare canonical IO-operators (<< and >>) as member-functions. The line
friend ostream& operator << (ostream& stream, const Vector2& other);
is not a declaration of a member function. It simply allows the free/non-member function ostream& operator << (ostream& stream, const Vector2& other); to access private members of Vector2.
Without this line you should get the error
'Vector2::x': cannot access private member declared in class 'Vector2'
(or something similar)
However, the error
"Function definition for operator << not found"
could arise when you have split declaration and definition in your real code. If you have the line
friend ostream& operator << (ostream& stream, const Vector2& other);
in Vector2 you also declared a free function ostream& operator << (ostream& stream, const Vector2& other); and simultaneously make it a friend of Vector2.
If you remove this line, the function isn't declared anywhere. (Of course the last part is only speculation, but the best guess I've got)

overload greater than operator with or without friend

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;

Operator Overloading in C++ (small error)

I have a small error with operator overloading that's been bugging me.
I've got a class:
class Fraction{
private:
//Variables
int numerator;
int denominator;
//Constructor
public:
//Methods
Fraction();
Fraction(int, int);
};
I also have this operator overloading function:
Fraction& operator+=(const Fraction& f);
It seems like it would build fine to me, but the compiler is giving me this error message:
In file included from Fraction.cpp:3:
./Fraction.h:31:11: error: overloaded 'operator+=' must be a binary operator
(has 1 parameter)
Fraction& operator+=(const Fraction& f);
^
1 error generated.
Every single example of += I've seen so far is identical to what I'm doing as far, from what I can tell. If someone could point out my stupidity, that would be great!
Either declare the operator as a member function of the class or if it is a non-class function then it shall have two parameters
For example
1 member function
class Fraction
{
private:
//Variables
int numerator;
int denominator;
//Constructor
public:
//Methods
Fraction();
Fraction(int, int);
Fraction& operator +=( const Fraction &rhs );
};
2. non-member function
class Fraction
{
private:
//Variables
int numerator;
int denominator;
//Constructor
public:
//Methods
Fraction();
Fraction(int, int);
friend Fraction& operator +=( Fraction &lhs, const Fraction &rhs );
};
Fraction& operator +=( Fraction &lhs, const Fraction &rhs ) { /* some code */ }
Take into account that then the operator is a non-class function you may not use this
Also the non-class operator should be a friend function of the class if there is no public access to corresponding data members through getters and setters.
You should put
Fraction& operator+=(const Fraction& f);
declaration inside class if it has to be binary operation. Alternatively you can declare this operator in global namespace taking two instances of Fraction, but make it friend of this class (as it needs access to private data) by declaring friendship in Fraction through:
friend Fraction& operator+=( Fraction& l, const Fraction& r);
You are defining a free function, it should have 2 parameters (binary operator).
Declare it inside the Fraction class instead.
If you overload the operator as a non-member function you need to write it like this
Fraction& operator+=(const Fraction& lhs, const Fraction& rhs);
This errors occurs when your overloaded operator is outside your class as global.
You should try give declaration of this operator into your class as:
Fraction& operator+=(const Fraction& f);
You can leave as you did but then you must change operator to this:
Fraction& operator+=(const Fraction& f, const Fraction& g);
Here you can find some more information in my post

C++ friend operator+ overloading

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;
}

How do I define friends in global namespace within another C++ namespace?

I'd like to define a binary operator on in the global namespace. The operator
works on a class that is defined in another namespace and the operator should get
access to the private members of that class. The problem I have is that I don't
know how to scope that global operator when making it a friend in the class definition.
I tried something like:
namespace NAME
{
class A {
public:
friend A ::operator * (double lhs, const A& rhs);
private:
int private_var;
};
}
A operator * (double lhs, const A& rhs)
{
double x = rhs.private_var;
...
}
The compiler (g++ 4.4) didn't know what to do with it. It seems that the line
friend A ::operator * ()
is evaluated as something like (pseudo-code)
(A::operator)
instead of
(A) (::operator)
If I leave out the :: in the declaration of the operator the compiling works but the operator is then in namespace NAME and not in the global namespace.
How can I qualify the global namespace in such a situation?
First, note that your operator declaration was lacking a namespace qualification for A:
NAME::A operator * (double lhs, const NAME::A& rhs)
and then the decisive trick is to add parentheses to the friend declaration like this, just as you proposed in your "pseudo-code"
friend A (::operator *) (double lhs, const A& rhs);
To make it all compile, you then need some forward declarations, arriving at this:
namespace NAME
{
class A;
}
NAME::A operator * (double lhs, const NAME::A& rhs);
namespace NAME
{
class A {
public:
friend A (::operator *) (double lhs, const A& rhs);
private:
int private_var;
};
}
NAME::A operator * (double lhs, const NAME::A& rhs)
{
double x = rhs.private_var;
}
Alexander is right, though -- you should probably declare the operator in the same namespace as its parameters.
This compiles, I assume without testing that it also works. Note the use of parentheses:
namespace NAME {class A; }
NAME::A operator * (double lhs, const NAME::A& rhs);
namespace NAME
{
class A {
public:
friend A (::operator *) (double lhs, const A& rhs);
private:
int private_var;
};
}
NAME::A operator * (double lhs, const NAME::A& rhs)
{
double x = rhs.private_var;
return rhs;
}
int main() {}
As Alexander mentions, though, your question doesn't explain why the operator isn't in namespace NAME. Either way it can be called as 1.0 * some_A_instance. So you may be creating needless trouble for yourself.
I don't know exact answer to your question.
But it's terrible bad idea to define operator outside namespace of its parameters (now you cut argument dependent lookup which is very usable for operators).
It is possible - you can enclose the declarator in parentheses: friend A (::operator * (double lhs, const A& rhs));
You also need to forward-declare both the class and the function.
namespace NAME {class A;}
NAME::A operator *(double lhs, const NAME::A& rhs);
// ...
namespace NAME
{
class A {
public:
friend A (::operator * (double lhs, const A& rhs));
private:
int private_var;
};
}
NAME::A operator *(double lhs, const NAME::A& rhs) {
//...
}
But I agree with Andreas that it would be better to define both in the same namespace if possible.