Why is there a difference when overloading different operators? - c++

Consider the following code snippet:
class Complex {
double real, im;
public:
Complex(double real, double im) {
this->real = real;
this->im = im;
}
Complex operator + (Complex const& sec) {
Complex ret(real + sec.real, im + sec.im);
return ret;
}
friend ostream& operator<<(ostream& os, const Complex& com);
};
ostream& operator << (ostream& os, const Complex& com) {
os << com.real << " " << com.im << "i";
return os;
}
Why doesn't the operator overloading of + have to be declared as friend as it will also want to access the private variables of the class from outside, similar to when overloading the << operator? At least that's what I thought but apparently this is not the case.

A member function can access all the variables of a class, public or private. You only need friend for functions or classes that aren't part of your class.

Related

Call to deleted constructor of std::__1::ostream error on operator<< overload

I am trying to get a function to be recognized as a friend but I can not figure out what I am doing wrong. I tried changing things to references and moving things in and out of the namespace and header cpp. There is nothing that I notice as the culprit for why this does not work.
The error I am getting is
error: call to deleted constructor of 'std::__1::ostream' (aka 'basic_ostream<char>')
return output;
^~~~~~
I'm thinking it might be a reference issue, or maybe something I forgot to import when I started. But I can't think of anything.
namespace N
{
class Complex
{
public:
// Contructors
Complex(double n, double i)
{
this->number = n;
this->imaginary = i;
}
Complex()
{
this->number = 0;
this->number = 0;
}
// Accessors
friend ostream operator<< (ostream& os, const Complex& a);
// Operator Overloads
Complex operator + (Complex b)
{
Complex c;
c.number = this->number + b.number;
c.imaginary = this->imaginary + b.imaginary;
return c;
}
private:
double number;
double imaginary;
};
ostream operator<<(ostream& output, const Complex& a)
{
output << fixed << setprecision(1) << a.number << " + " << a.imaginary << "i";
return output;
}
}
You need to return the std::ostream by reference. That means you need
namespace N
{
class Complex
{
public:
friend std::ostream& operator<< (std::ostream& os, const Complex& a);
// ^^^^^^^^^^^^^^
private:
// ...
};
std::ostream& operator<<(std::ostream& output, const Complex& a)
//^^^^^^^^^^^^
{
return output << std::fixed << std::setprecision(1)
<< a.number << " + " << a.imaginary << "i";
}
}
This is because, the std::ostream is non-copyable:
protected:
basic_ostream( const basic_ostream& rhs ) = delete; (2) (since C++11)
When you return by non-reference, it will be return by copy in operator<<, which required the copy constructor call. Since it is deleted, you get the error.

C++ operator I/O overloading

I've encountered a strange problem while overloading << operator for a Complex class (The Complex class and overload function are not complete, but the meaning should be the same - BUT if you feel there is missing some important part, just prompt me ;-) ):
class Complex {
float m_fReal;
float m_fImaginary;
public:
Complex();
Complex(float real, float imaginary);
Complex add(Complex) const;
friend std::ostream& operator<<
(std::ostream& out, Complex cComplex);
};
Overload function:
std::ostream& operator<<(std::ostream& out, Complex cComplex) {
out << cComplex.m_fReal << " " << cComplex.m_fImaginary;
return out;
}
Add function:
Complex Complex::add(Complex cComplex) const {
return Complex (m_fReal + cComplex.m_fReal,
m_fImaginary + cComplex.m_fImaginary);
}
Function call in main:
Complex x(1,1), y(2,2);
cout << "x+y=" << x.add(y) << endl;
While the above works, this does not (only parts that differ).
Declaration in Complex class:
friend std::ostream& operator<<
(std::ostream& out, Complex& cComplex);
Definition:
std::ostream& operator<<(std::ostream& out, Complex& cComplex) {
out << cComplex.m_fReal << " " << cComplex.m_fImaginary;
return out;
}
My intention was to pass the Complex class by reference. Can anybody explain to me, what went wrong in this code and why?
You need to accept the object to output by const reference. You're accepting it as a non-const reference to which the return from add cannot be bound.
std::ostream& operator<<(std::ostream& out, const Complex& cComplex) {
This design/behavior is to prevent mistakes where a function expects to mutate the value of a reference parameter, but the reference has been bound to an unnamed temporary object, in other words memory that can't be accessed again, rendering the changes pointless.
Your definition should be
std::ostream& operator<<(std::ostream& out, const Complex& cComplex) {
out << cComplex.m_fReal << " " << cComplex.m_fImaginary;
return out;
}
cComplex needs to be const qualified for you to access its private variables using "."

Private members of class - within this context

I get weird notification that I'm using private members of class - which is entirely valid, but I though that I'm allowed to do so, since I did say that the method I'm using is a friendly one.
Take a look at this:
#include <iostream>
using namespace std;
class complex {
private:
double Re, Im;
public:
complex(): Re(0.0), Im(0.0){}
complex(double Re, double Im): Re(Re), Im(Im){}
double getRe() const { return Re; }
double getIm() const { return Im; }
friend complex operator+(const complex&, const complex&);
friend ostream& operator<<(ostream&, const complex&);
friend istream& operator>>(istream &, const complex &); // FRIENDLY FUNCTION
};
complex operator+(const complex& a, const complex& b) {
double r, i;
r = a.getRe()+ b.getRe();
i = a.getIm() + b.getIm();
return complex(r, i);
}
ostream& operator<<(ostream& out, const complex &a) {
out << "(" << a.getRe() << ", " << a.getIm() << ")" << endl;
return out;
}
istream &operator>>(istream &in, complex &c)
{
cout<<"enter real part:\n";
in>>c.Re; // ** WITHIN THIS CONTEXT ERROR **
cout<<"enter imag part: \n";
in>>c.Im; // ** WITHIN THIS CONTEXT ERROR **
return in;
}
int main(void) {
complex a, b,c;
cin >> a;
cin >> b;
c = a+b;
cout << c;
}
Should I declare some sort of setFunction within the class in order to get the values which are private ?
istream& operator>>(istream &, const complex &);
is not the same as
istream &operator>>(istream &in, complex &c);
Spot the difference left as exercise to the reader.

Fixing "this" error in c++

I'm still new to c++ and I was wondering why I keep getting the error "invalid use of 'this' in non-member function" for every instance of "this" in my cpp file.
cpp file (just method)
ostream & operator<< (ostream & outS, Complex & rhs) {
cout << this->real;
if (this->imag < 0) {
cout << "-";
if (this->imag != -1)
cout << (-this->imag);
cout << "i";
} else if (this->imag >0){
cout << "+";
if (this->imag != 1)
cout << this->imag;
cout << "i";
return outS;
}
header file (part of)
public:
friend ostream & operator<< (ostream&, Complex&);
I also seem to be getting the error "'Complx' does not name a type
Complx::Complex (const Complex& object)"
^
cpp file
Complx::Complex (const Complex& object) {
real = object.real;
imag = object.imag;
}
header file
public:
Complex (const Complex&);
Any help would be much appreciated, and I can post the rest of my code if needed (I figured just posting parts of it would be easier to read).
this refers to your current object -- the object that the method is a part of. When your method stands alone, it's not part of an object so this has no meaning. It appears that instead of this-> you intend to refer to rhs..
In your operator<<, it is NOT a member of your class. Thus, it does not have this pointer, which is only for class non-static members.
class Complex
{
double imag, real;
public:
Complex(const _real=0.0, const _imag=0.0);
Complex(const Complex&);
// friend functions are not member of the class
friend ostream& operator<< (ostream&, Complex&);
// this is a member of the class
Complex operator+(Complex& another)
{
// I am a member so I have 'this' pointer
Complex result;
result.real = this->real + another.real;
result.imag = this->imag + another.imag;
return result;
}
};
ostream& operator<<(ostream& stream, Complex& rhs)
{
// I do not have 'this' pointer, because I am not a member of a class
// I have to access the values via the object, i.e. rhs
stream << rhs.real << "+" << rhs.imag << 'i';
return stream;
}
Yet my question is, why do you want to use 'friend operator<<'? IMHO it should not be a friend of the class, instead, the class should provide functions like double image() const { return this->imag; }, and the non-friend operator<< can access the values via these functions.

operator<< overloading [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Operator overloading
I didn't find any thing that could help me in this subject...
I'm trying to over load the << operator, this is my code:
ostream& Complex::operator<<(ostream& out,const Complex& b){
out<<"("<<b.x<<","<<b.y<<")";
return out;
}
this is the declaration in the H file:
ostream& operator<<(ostream& out,const Complex& b);
I get this error:
error: std::ostream& Complex::operator<<(std::ostream&, const Complex&) must take exactly one argument
what and why I'm doing wrong?
thanks
your operator << should be free function, not Complex class member in your case.
If you did your operator << class member, it actually should take one parameter, which should be stream. But then you won't be able to write like
std::cout << complex_number;
but
complex_number << std::cout;
which is equivalent to
complex_number. operator << (std::cout);
It is not common practice, as you can note, that is why operator << usually defined as free function.
class Complex
{
int a, b;
public:
Complex(int m, int d)
{
a = m; b = d;
}
friend ostream& operator<<(ostream& os, const Complex& complex);
};
ostream& operator<<(ostream& os, const Complex& complex)
{
os << complex.a << '+' << complex.b << 'i';
return os;
}
int main()
{
Complex complex(5, 6);
cout << complex;
}
More info here
As noted, the streaming overloads need to to be free functions, defined outside of your class.
Personally, I prefer to stay away from friendship and redirect to a public member function instead:
class Complex
{
public:
std::ostream& output(std::ostream& s) const;
};
std::ostream& operator<< (std::ostream& s, const Complex& c)
{
return c.output(s);
}