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)
// ^^^^^^^
Related
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)
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.
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.
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.
Hi I am rather new to C++, I have just started learning it after learning some Java basics.
I have pre-existing code were it has overloaded the >> operator, however after watching many tutorials and trying to understand the issue, I thought I would ask here.
Rational cpp file:
#include "Rational.h"
#include <iostream>
Rational::Rational (){
}
Rational::Rational (int n, int d) {
n_ = n;
d_ = d;
}
/**
* Creates a rational number equivalent to other
*/
Rational::Rational (const Rational& other) {
n_ = other.n_;
d_ = other.d_;
}
/**
* Makes this equivalent to other
*/
Rational& Rational::operator= (const Rational& other) {
n_ = other.n_;
d_ = other.d_;
return *this;
}
/**
* Insert r into or extract r from stream
*/
std::ostream& operator<< (std::ostream& out, const Rational& r) {
return out << r.n_ << '/' << r.d_;
}
std::istream& operator>> (std::istream& in, Rational& r) {
int n, d;
if (in >> n && in.peek() == '/' && in.ignore() && in >> d) {
r = Rational(n, d);
}
return in;
}}
Rational.h file:
#ifndef RATIONAL_H_
#define RATIONAL_H_
#include <iostream>
class Rational {
public:
Rational ();
/**
* Creates a rational number with the given numerator and denominator
*/
Rational (int n = 0, int d = 1);
/**
* Creates a rational number equivalent to other
*/
Rational (const Rational& other);
/**
* Makes this equivalent to other
*/
Rational& operator= (const Rational& other);
/**
* Insert r into or extract r from stream
*/
friend std::ostream& operator<< (std::ostream &out, const Rational& r);
friend std::istream& operator>> (std::istream &in, Rational& r);
private:
int n_, d_;};
#endif
The function is from a pre-existing class called Rational which takes two ints as parameters. Here is the function to overload >> :
std::istream& operator>> (std::istream& in, Rational& r) {
int n, d;
if (in >> n && in.peek() == '/' && in.ignore() && in >> d) {
r = Rational(n, d);
}
return in;
}
And I'm trying to use it like this, after seeing a few tutorials. (The error I am getting is "Ambiguous overload for operator>> in std::cin>>n1 :
int main () {
// create a Rational Object.
Rational n1();
cin >> n1;
}
Like I said I'm new to this whole overloading operators thing, and figure someone here would be able to point me in the right direction on how to use this function.
Change Rational n1(); to Rational n1;. You've ran into the most vexing parse. Rational n1(); does not instantiate a Rational object, but declares a function named n1 which returns a Rational object.
// create a Rational Object.
Rational n1();
this doesn't create new object but declares a function taking no arguments and returning Rational
you probably meant
// create a Rational Object.
Rational n1;
cin>>n1;