I've asked a similar question before (Why the code doesn't work on CodeBlocks,but on VS works).
Now a new error confused me.
cout << ++a1 << endl; will call the function operator double().
If in the code Fraction& operator++() I remove the & to make it Fraction operator++(), it will call the ostream& operator<<(ostream& os, Fraction&& obj).
#include <iostream>
using namespace std;
class Fraction
{
private:
int fenzi, fenmu;
public:
Fraction(int a, int b) :fenzi(a), fenmu(b) {}
operator double()
{
return 1.0* fenzi / fenmu;
}
friend ostream& operator<<(ostream& os, Fraction&& obj)
{
os << obj.fenzi << "/" << obj.fenmu;
return os;
}
Fraction& operator++()
{
fenzi++;
fenmu++;
return *this;
}
Fraction operator++(int)
{
Fraction tmp(fenzi, fenmu);
fenzi++;
fenmu++;
return tmp;
}
};
int main()
{
Fraction a1(9, 11), a2(1, 2);
cout << double(a2) << endl;
cout << ++a1 << endl;
cout << a1++ << endl;
return 0;
}
I wonder why is the output different?
Fraction operator++() and Fraction& operator++(), the former returns a copied one, and the latter returns the original one. But their types are both Fraction. I think it should have both called ostream& operator<<(ostream& os, Fraction&& obj).
Fraction operator++() output(I expected):
0.5
10/12
10/12
Fraction& operator++() output:
0.5
0.833333
10/12
operator double()
{
return 1.0* fenzi / fenmu;
}
Is the implicit conversion operator. Adding the explicit keyword to the operator double() will help with this because the compiler won't implicitly convert a Fraction into a double without you explicitly casting it into a double. The addition would look like:
explicit operator double()
{
return 1.0* fenzi / fenmu;
}
The correct output stream operator is defined as
friend ostream& operator<<(ostream& os, Fraction& obj). You defined it as friend ostream& operator<<(ostream& os, Fraction&& obj)
Fraction&& is a rvalue reference instead of a lvalue reference (Fraction&). The compiler used the implicit conversion operator because the operator++ (in either definition) returns a lvalue (reference) instead of a rvalue reference which was defined as the parameter of the output stream operator.
Related
This question already has answers here:
What are the basic rules and idioms for operator overloading?
(8 answers)
Closed 1 year ago.
Firstly, i'm pretty new to C++ and OOP, so sorry if asking silly questions. So, here it is, I overloaded the "<<" and "++" (postfix and prefix) and they work fine alone. But they seem to not work when combined. I don't get why, both ++-s return a foo type object, so I thinked that "<<" should work fine...
#include <iostream>
using namespace std;
class foo
{
int x;
public:
foo()
{
x=10;
}
foo(const foo& f1)
{
this->x=f1.x;
cout<<"OK"; /// testing if it really works
}
foo operator ++ ()
{
++x;
return *this;
}
foo operator ++ (int)
{
x++;
return *this;
}
friend istream& operator>>(istream& in, foo& S);
friend ostream& operator<<(ostream& out, foo& S);
};
istream& operator>>(istream& in, foo& S)
{
in>>S.x;
return in;
}
ostream& operator<<(ostream& out, foo& S)
{
out<<S.x;
return out;
}
int main()
{
foo A, B, C;
cout<<A;
//cout<<++A; //error: cannot bind non-const lvalue reference of type 'foo&' to an rvalue of type 'foo'
//cout<<A++; //error: no match for 'operator<<' (operand types are 'std::ostream' {aka 'std::basic_ostream<char>'} and 'foo')
return 0;
}
Your stream output overload should take your foo references as const. After all, they shouldn't be modifying the foo's passed in:
friend istream& operator<<(istream& in, const foo& S);
A non-const reference parameter (like your foo& S), must have an l-value passed to it. Since your increment operator returns an r-value, you're seeing the compiler error (which says exactly this). To be able to take both l and r-values, you need to make the change to a const-reference parameter above.
In addition, your prefix increment operator should return by reference:
foo& operator ++ ()
{
++x;
return *this;
}
For more on the basic rules and idioms for overloading, read here: https://stackoverflow.com/a/4421719/2602718
In addition to scohe001's answer, your postfix and prefix operators also need correction.
Prefix operator should return a reference to the object being incremented. You're returning a copy of *this instead. Your return type should be foo& as such:
foo& operator ++ ()
{
++x;
return *this;
}
And in the postfix operator, you need to first remember the state of the object, i.e. make a copy of the object before modification, and then modify the object, and finally return the unmodified copy, like this:
foo operator ++ (int)
{
foo temp(*this);
++x;
return temp;
}
Here's your code, fixed up. I added comments where I made changes.
#include <iostream>
using namespace std;
class foo {
int x;
public:
foo() { x = 10; }
foo(const foo& f1) {
this->x = f1.x;
cout << "OK"; /// testing if it really works
}
// Changed return type
foo& operator++() {
++x;
return *this;
}
// Re-wrote body
foo operator++(int) {
foo tmp = *this;
++(*this);
return tmp;
}
friend istream& operator>>(istream& in, foo& S);
friend ostream& operator<<(ostream& out, const foo& S); // Added const
};
istream& operator>>(istream& in, foo& S) {
in >> S.x;
return in;
}
// Matched added const
ostream& operator<<(ostream& out, const foo& S) {
out << S.x;
return out;
}
int main() {
foo A, B, C;
cout << A << '\n';
cout << ++A << '\n';
cout << A++ << '\n';
return 0;
}
Prefix ++ and postfix ++ behave differently. This is observed when testing the operators out on a regular int.
int x = 5;
std::cout << x++ << '\n';
std::cout << ++x << '\n';
You get the output:
5
7
Postfix increment returns the original value but still increments. Prefix increment returns the incremented value. This is why prefix needs to return a reference. It returns itself, and we do that with a reference.
So what happened in the short code example above was x had its original value (5) returned, but the postfix increment still incremented, so x had a value of 6. Then the prefix print ensured that the incremented x was returned and it printed 7.
The change to operator<<() is convention. When printing an object, I don't want to modify it, so I pass it as a reference to const.
I have a header file and a .cpp file. I am trying to implement a prefix and postfix operator overload but I keep getting this error when setting up the overload.
fraction.h
#ifndef FRACTION_H
#define FRACTION_H
#include <iostream>
using namespace std;
class Fraction
{
public:
Fraction();
Fraction(int, int);
int getTop() {return m_top;}
int getBottom() {return m_bottom;}
void set(int t, int b) {m_top=t; m_bottom=b; reduce();
}
protected:
private:
void reduce();
int gcf(int, int);
int m_top;
int m_bottom;
};
Fraction& operator ++ (Fraction);
Fraction operator++(Fraction, int);
#endif
Main.cpp
#include <iostream>
using namespace std;
#include "fraction.h"
int main {
cout << "The fraction is" << f;
cout << "The output of ++f is " << (++f) << endl;
cout << "The fraction is" << f;
cout << "The output of f++ is " << (f++) << endl;
cout << "The fraction is" << f;
return 0;
}
Fraction& Fraction::operator ++ (Fraction){
// Increment prefix
m_top += m_bottom;
return *this;
}
Fraction Fraction::operator ++ (Fraction, int){
//Increment postfix
}
These are the two errors I get:
prefix error: "Parameter of overloaded post-increment operator must have type 'int' (not 'Fraction')"
postfix error: "Overloaded 'Operator++' must be a unary or binary operator (has 3 parameters)"
Is the prefix error actually an error with my ide? I know it must be 'int' for post-increment, but I am trying to do a pre-increment. I use xcode.
You declared the operators outside the class as non-class functions
Fraction& operator ++ (Fraction);
Fraction operator++(Fraction, int);
however then you are trying to define them like class member functions
Fraction& Fraction::operator ++ (Fraction){
// Increment prefix
m_top += m_bottom;
return *this;
}
Fraction Fraction::operator ++ (Fraction, int){
//Increment postfix
}
Either declare them as class member functions the following way
class Fraction
{
public:
Fraction & operator ++();
Fraction operator ++( int );
//...
And in this case the definition for example of the preincrement operator can look like
Fraction & Fraction::operator ++(){
// Increment prefix
m_top += m_bottom;
return *this;
}
Or declare them as non-class function that are friends of the class because they need to have access to private data members of the class
class Fraction
{
public:
friend Fraction & operator ++( Fraction & );
friend Fraction operator ++( Fraction &, int );
//...
And in this case the definition for example of the preincrement operator can look like
Fraction & operator ++( Fraction &f ){
// Increment prefix
f.m_top += f.m_bottom;
return f;
}
You declared the functions as free functions
Fraction& operator ++ (Fraction);
Fraction operator++(Fraction, int);
but you are defining them as member functions.
Fraction& Fraction::operator ++ (Fraction){ ... }
Fraction& Fraction::operator ++ (Fraction, int){ ... }
Since member functions have an implicit this parameter, your member functions have three parameters (this, Fraction, and int).
Decide whether you want the functions to be free or member. If you want them to be free, then define them as free rather than member. If you want them to be member, then declare them as member and adjust the declarations as noted by #crayzeewulf above.
A member function has an implicit *this pointer which always points to the class object the member function is working on. The parameter we had to list explicitly in the friend function version (which doesn’t have a *this pointer) becomes the implicit *this parameter in the member function version.
Try making it a non member function.Then you can pass the parameter
Otherwise remove the parameter.
int main() {
Fraction f;
cout << "The fraction is" << f;
cout << "The output of ++f is " << (++f) << endl;
cout << "The fraction is" << f;
cout << "The output of f++ is " << (f++) << endl;
cout << "The fraction is" << f;
return 0;
}
Fraction& Fraction::operator++ ()
{
// Increment prefix
m_top += 1;
return *this;
}
const Fraction Fraction::operator++ (int)
{
//Increment postfix
Fraction temp = *this;
++(*this);
return temp;
}
ostream& operator<<(ostream &os, const Fraction& f)
{
os << f.m_top << endl;
return os;
}
Fraction::Fraction(const Fraction& f)
{
m_top = f.m_top;
m_bottom = f.m_bottom;
}
Fraction::Fraction(int t, int b) :m_top(t), m_bottom(b){}
Fraction::Fraction() : m_top(1), m_bottom(1){}
class Fraction
{
public:
Fraction();
Fraction(int, int);
Fraction(const Fraction& f);
int getTop() { return m_top; }
int getBottom() { return m_bottom; }
void set(int t, int b) {
m_top = t; m_bottom = b; reduce();
}
Fraction& operator ++ ();
const Fraction operator++(int);
friend ostream& operator<<(ostream &os,const Fraction& f);
protected:
private:
void reduce();
int gcf(int, int);
int m_top;
int m_bottom;
};
#endif
I am a beginner trying to learn c++ so probably my question is very basic. Consider the following pice of code:
class pounds
{
private:
int m_p;
int m_cents;
public:
pounds(){m_p = 0; m_cents= 0;}
pounds(int p, int cents)
{
m_p = p;
m_cents = cents;
}
friend ostream& operator << (ostream&, pounds&);
friend istream& operator>>(istream&, pounds&);
};
ostream& operator<< (ostream& op, pounds& p)
{
op<<p.m_p<<"and "<<p.m_cents<<endl;
return op;
}
istream& operator>>(istream& ip, pounds& p)
{
ip>>p.m_p>>p.m_cents;
return ip;
}
This compiles and seems to work but I am not returning a reference to a local variable? Thanks in advance.
It's correct, since there are no local variables, there are references, that will be passed, when operators will be called.
And i suggest you to change signature of operator << to
std::ostream& operator << (ostream& os, const pounds& p);
since, p is not modified in function.
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);
}
hey, i got something that i cannot understand ,there are two types of solutions for overloading this operator 1 is including the friend at the start of the method and the other 1 goes without the friend.
i would very much like if some1 explain whats the difference between them advantages / disadvantages.
for example overloading the operator << in class rational:
class Rational:
{
private: int m_t,m_b;
...
friend ostream& operator<<(ostream& out,const Rational& r) // option 1
{ return out << r.m_t << "/" <<r.m_b;} // continue of option 1
ostream& operator<<(ostream& out,const Rational& r){return r.print();} // option 2
virtual ostream& print(ostream& out) const // continue of option 2
{ //
return out<<m_t << "/" << m_b;
} //
};
i was told that the second option isnt correct , if some1 can correct me about it i would much appriciate it.
thanks in advance.
The short answer: Option #2 actually isn't an option, but a syntax error, because it tries to define a binary operator as a member passing two operands.
The somewhat longer answer: If you make the second operand a free function (not a member of the class), this will work. Which one is preferable depends on the circumstances and your preferences. For starters: The disadvantage of the first is that it allows operator<< to access everything in Rational (including private helper functions), while the disadvantage of the second is that you introduce a function to the class' public API that nobody needs.
operator<< (for ostream) needs to be a free function (since the left-hand argument is a stream, not your class).
The friend keyword makes it a free function (a free function that has access to the private members).
However, if this functionality can be implemented in terms of the public interface, it is better to do so and just use a non-friend free function.
class Rational:
{
private: int m_t,m_b;
public:
...
virtual ostream& print(ostream& out) const
{
return out<<m_t << "/" << m_b;
}
};
ostream& operator<<(ostream& out,const Rational& r)
{
return r.print(out);
}
Consider a function that should output the num and den of Rational:
ostream& operator<<(ostream& out, const Rational& r)
{
return out;
}
Unfortunately, this is just a global function. Like any other global function, it cannot access the private members of Rational. To make it work with Rational objects, you need to make it friend of Rational:
class Rational
{
private: int m_t,m_b;
// ...
friend ostream& operator<<(ostream& out, const Rational& r);
};
ostream& operator<<(ostream& out, const Rational& r)
{
out << r.m_t << "/" <<r.m_b;
return out;
}
The friend ostream& operator<<(ostream& out, const Rational& r); inside Rational class indicates that ostream& operator<<(ostream& out, const Rational& r) function can directly use Rational's private members.
Now when you write:
Rational r(1, 2); // Say, it sets num and den
cout << r;
the following function call is made:
operator<<(cout, r);
Can you write operator<< as a member function of Rational? That's simply not possible because of the above conversion where cout has to be first parameter. If you make operator<< as a member of Rational:
class Rational
{
private: int m_t,m_b;
// ...
public:
ostream& operator<<(ostream& out) const
{
out << r.m_t << "/" <<r.m_b;
return out;
}
};
you need to call it this way:
Rational r(1, 2);
r.operator<<(cout);
which is ugly.