How to output multiplied user created class c++ - c++

I am working on an assignment overloading operators for a user-created class of rational numbers but can not output two "Rational" objects in the same line. For example:
std::cout<<5*10<<std::endl;
Outputs 50 just fine. However when I try to do,
std::cout<<Rational_1*Rational_2<<std::endl;
I receive an error. If I instead assign the value to a third rational such as
Rational_3=Rational_1*Rational_2;
std::cout<<Rational_3<<std::endl;
Then the program outputs just fine. I have brought this up to my professor but even he does not know how to fix it. Any explanation as to why this is happening would be helpful. I would like to know why this is an issue instead of just simply getting a piece of code that works.
#include <iostream>
using namespace std;
class Rational{
public:
Rational();
Rational(int whole_number);
Rational(int numerator_input,int denominator_input);
friend Rational operator *(Rational rat_1, Rational rat_2);
` friend ostream& operator <<(ostream& out,Rational& output);
void simplify();
private:
int numerator,denominator;
};
int main(){
Rational r1(2,3),r2(3,4),r3;
r3=r1*r2;
cout<<r3<<endl;
//cout<<r1*r2<<endl;
return 0;
}
Rational::Rational(){
numerator=0;
denominator=1;
}
Rational::Rational(int whole_number){
numerator=whole_number;
denominator=1;
}
Rational::Rational(int numerator_input,int denominator_input){
numerator=numerator_input;
if(denominator_input==0){
cout<<"A rational number can not have a 0 in the denominator\n";
exit (5);
}
denominator=denominator_input;
simplify();
}
ostream& operator <<(ostream& out,Rational& output){
out<<output.numerator<<"/"<<output.denominator;
return out;
}
Rational operator *(Rational rat_1, Rational rat_2){
Rational rat_3;
rat_1.simplify();
rat_2.simplify();
rat_3.numerator=rat_1.numerator*rat_2.numerator;
rat_3.denominator=rat_1.denominator*rat_2.denominator;
rat_3.simplify();
return rat_3;
}
void Rational::simplify(){
//Flip negative sign to numerator
for(int counter=1000000;counter>0;counter--){
if((numerator%counter==0)&&(denominator%counter==0))
{
numerator=numerator/counter;
denominator=denominator/counter;
}
}
}

The difference between the operator<< that takes an int as in your first snippet is that it takes it's argument by value.
Your overloaded operator<< takes a Rational object by reference and Rational_1*Rational_2 returns an temporary object, temporary objects are not allowed to bind to non-const references.
Either take your argument by value or by const& to fix this:
friend ostream& operator <<(ostream& out, const Rational& output);
Or
friend ostream& operator <<(ostream& out, Rational output);

Declare the operator like
friend ostream& operator <<(ostream& out, const Rational& output);
^^^^^
You may not bind a temporary object to a non-constant lvalue reference.

Related

++ pre-fix operator overload is not working with <<

Bit of a new C++ dev here. I have a class Rational used to represent rational numbers and allow the user to perform arithmetic and relational operations on them. I overloaded all the operators and they're all working properly except when I try to combine the ++/-- pre-fix operators (e.g., --Rational) or the +/- unary operators with the << output operator, as in:
Rational num(7, 2); // initializes rational to 7/2 (fraction)
cout << --num; // should change val to 5/2 (decrements by one)
// error: no match for 'operator<<'(operand types are 'std::ostream' {aka 'std::basic_ostream<char>'} and 'Rational')
or:
Rational num(1, 10);
cout << -num; // should change to -1/10
// error: no match for 'operator<<'(operand types are 'std::ostream' {aka 'std::basic_ostream<char>'} and 'Rational')
Which I don't understand why, because I've overloaded all of these operators to return a Rational object, and I've overloaded the << operator to accept a Rational object as well. Interestingly enough, when I try this:
Rational num(5, 3);
cout << num;
It works as intended. So can someone tell me what's going on here?
Relevant code for the class:
class Rational
{
private:
// Instance variables declarations
int numerator, denominator;
public:
// Constructors declarations
Rational(int numer_val, int denom_val = 1);
Rational();
// Unary operators declarations
friend Rational operator +(const Rational &num);
friend Rational operator -(const Rational &num);
friend Rational operator ++(Rational &num);
friend Rational operator --(Rational &num);
// I/O operators
friend ostream& operator <<(ostream &outs, Rational &num);
};
// Constructors definitions
Rational::Rational(int numer_val, int denom_val) : numerator(numer_val)
{
set_denominator(denom_val); // irrelevant
simplify(); // irrelevant
}
Rational::Rational() : Rational(0) { }
// Unary operators definitions
Rational operator +(const Rational &num)
{
return Rational(+num.numerator, num.denominator);
}
Rational operator -(const Rational &num)
{
return Rational(-num.numerator, num.denominator);
}
Rational operator ++(Rational &num)
{
num.numerator += num.denominator;
return num;
}
Rational operator --(Rational &num)
{
num.numerator -= num.denominator;
return num;
}
// I/O operators
ostream& operator <<(ostream &outs, Rational &num)
{
outs << to_string(num.numerator) + "/" + to_string(num.denominator);
return outs;
}
The second argument of your operator<< binds to an l-value reference:
ostream& operator <<(ostream &outs, Rational & num)
// ^
But all your operators return r-values. So for example, when you do:
cout << -num;
you are trying to bind an l-value reference to an r-value, which is not allowed.
You can fix this by changing operator<< to accept a const reference:
ostream& operator <<(ostream &outs, Rational const & num)
// ^^^^^^^

No operator "=" matches these operands. I have overloaded it but it doesn't seem to be working properly

I have overloaded the "=" operator to accept objects of my class rational, but it does not seem to be working. Here are my headers and my class definition
#include <iostream>
#include <assert.h>
#include <fstream>
using namespace std;
class rational {
public:
rational();
rational(int numerator, int denominator);
rational(const rational& r);
int numerator() const;
int denominator() const;
const rational& operator = (const rational& rhs); //this is what I'm having issues with
private:
int myNumerator, myDenominator;
void reduce();
};
Here is my overload implementaion (which I have below main):
const rational& rational::operator = (const rational& rhs) {
if (*this != rhs) { //added asterisk, otherwise operator would not work
myNumerator = rhs.numerator();
myDenominator = rhs.denominator();
}
return *this;
}
And below that I am having issues using the "=" operator in the following implementation:
istream& operator>>(istream& is, const rational& r) {
char divisionSymbol;
int numerator = 0, denominator = 0;
is >> numerator >> divisionSymbol >> denominator;
assert(divisionSymbol == '/');
assert(denominator != 0);
rational number(numerator, denominator);
r = number; /* Error: no operator matches these operands (more specifically no operator found
which takes a left-hand operand of type 'const rational') but I am unsure how to fix that as the
assignment operator only takes one parameter (unless I am mistaken)*/
return is;
}
I cannot for the life of me think of what is not working, possibly a syntax issue? And the professor I have is very old-school so possibly an outdated practice? Any tips would be appreciated.
Problem is not with '=' operator overloading function. Issue is with '>>' operator overloading function. You declared r as const reference parameter and you are trying to modify it by assigning 'number' object to it.
If you want to modify 'r', you should declare 'r' as just reference as below.
istream& operator>>(istream& is, rational& r)

How to overload operator+ if the calling object is not a class object?

Class fraction
{
public:
fraction operator+ (const fraction& fr) const;
private:
int num; //numerator
int den; //denominator
};
I wanted to overlaod the operator+ so that it perfoms the multiplication of an integer constant (calling object) and a fraction.
fraction fraction::operator+ (const fraction& fr) const
{
fraction result;
result.num = fr.num + fr.den * (*this);
//error message says invalid operands to binary exprssion ('int' and 'constant fraction')
result.den = fr.den;
simplified_fr(result); // a helper function to simplify the resulted fraction
return result;
}
It seems that the problem is about the type of calling object. I intended to make it a constant integer but the computer thought it was a 'const fraction'. Can someone please advise me why this happened and how can I fix it? Thank you in advance!!!
I assume you would like to do achieve something like this:
fraction fract;
fraction fract2 = 2 + fract;
The answer is that you cannot overload member method operator+ for non-class objects. BUT you can define/overload global operator+ function:
fraction operator+(int num, const fraction& rFrac)
{
//your implementation
}
You will probably need access to private members of fraction class. That can be acomplished by making operator+ a friend:
class fraction
{
//...
friend fraction operator+(int num, const fraction& rFrac);
//...
}

C++ error with operator overloading

I am trying to make program that uses operator overloading to do basic math operations on rational numbers. I keep getting an errors in the functions where it says i must have an arithmetic of enum type. Also I get an error istream where it says that the numerator and denominator are undefined.
Here is the header file:
#ifndef rational_H
#define rational_H
#include <iostream>
using namespace std;
class Rational
{
friend ostream & operator<<(ostream & , const Rational &);
friend istream & operator<<(istream & , const Rational &);
public:
// default constructor
Rational(int = 0, int = 1);
// overload operators for "normal" operation
Rational operator+(const Rational&);
Rational operator-(const Rational&);
Rational operator*(const Rational&);
Rational operator/(const Rational&);
operator double();
// overload relational operators for "normal" operation
bool operator>(const Rational&) const;
bool operator<(const Rational&) const;
bool operator>=(const Rational&) const;
bool operator<=(const Rational&) const;
bool operator==(const Rational&) const;
bool operator!=(const Rational&) const;
protected:
int *numerator;
int *denominator;
void reduction(void);
};
#endif
// this part of code is from my rational cpp file//
// default constructor//
Rational::Rational( int n, int d )
{
*numerator =1 ;
// sets numerator
if(d == 0)
d = 1; // If denominator is zero then set to one.
*denominator = 0;
// sets denominator
reduction(); // store the fraction in reduced form
}
// all the other operators have the same error as well//
Rational Rational::operator-(const Rational&a)
{
Rational sub;
sub.numerator = *this->numerator * a.denominator -//the error is with the 'a'needs to be an arithmetic type or enum type//
*this->denominator * a.numerator;
sub.denominator = *denominator * a.denominator;
sub.reduction();
return sub;
}
//also the istream part has an error where the denominator and numerator is underfined as well//
istream& operator >> ( istream& inputStream, Rational& rnum )
{
inputStream>>rnum.*numerator;//numerator and denmoinator undefined for some reason//
inputStream.ignore(1);
inputStream>>rnum.*denominator;
return inputStream;
}
There are multiples small errors in your code.
First of all you should not be using pointers for these members, it does not bring any advantages.
But as you chose this way, you have to dereference them each time you want to read or update them, which hasn't be done in your operator- implementation, and incorrectly in your operator>> implementation (the asterisk needs to be put before the whole expression).
Next error in the code you provided, you marked as friend operator<<(istream & , const Rational &) in your class definition, but it should have been operator>>. And this declaration needs to match the definition that appears next (i.e., remove the const of the second argument, which obviously has to be mutated).
And, last but not least, the undefined behavior caused by all the dereferencing of you uninitialized pointers…
This is probably a copy and past error. The line
friend istream & operator<<(istream & , const Rational &);
should be
friend istream & operator>>(istream & , Rational &);
Your implementation later on in the file has:
istream& operator >> ( istream& inputStream, Rational& rnum )
{
...
}
It matches the second declaration, not the first one.

overloading the << operator in c++

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.