Fractions class in c++ explaination [closed] - c++

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Can someone just explain whats going in this code? You don't have to go line by line but a general summary would be really helpful. It's similar to other fraction class c++ code so you don't have to completely refer to this code.
#include<iostream>
using namespace std;
class Fraction
{
private:
int num, den;
public:
Fraction(int n = 1, int d = 2) : num(n), den(d) { }
void show() { cout«num«”/”«den; }
Fraction operator+(Fraction f) const
{ return Fraction(num+f.num, den+f.den); }
Fraction operator-(Fraction f) const
{ return Fraction(num-f.num, den-f.den); }
Fraction operator*(Fraction f) const
{ return Fraction(num*f.num, den*f.den); }
Fraction operator/(Fraction f) const
{
int rNum = (f.den*num)/den;
return (rNum, f.num);
}
friend ostream& operator«(ostream& out, Fraction& f)
{ cout«f.num«”/”«f.den; return out; }
friend istream& operator»(istream& in, Fraction& f)
{ cout«”\nEnter Numerator: “; cin»f.num; cout«”Enter Denominator: “;
cin»f.den; cout«f.num«”/”«f.den; return in; }
int ndMax()
{ return (num<=den) ? num:den; }
void reduce()
{
for(int i = 2; i<=ndMax(); i++)
if(num%i == 0 && den%i == 0)
{ num = num/i; den = den/i; i = 1; }
}
}; //
int main()
{
Fraction f1(5, 6);
Fraction f2(80, 1001);
cout«f1«” and “«f2«endl;
Fraction f3 = f1/f2;
f3.reduce(); cout«f3;
cout«endl;
return 0;
}

// This declares a dependency on the system module, iostream. Specifically, this code uses the
// system provided objects, cout, and cin, for output and input.
#include <iostream>
// This says if the compiler cannot find a symbol, it should try looking in the namespace, std.
using namespace std;
// This defines a type called, Fraction.
class Fraction {
private:
// This declares two private member variables, num, and den, presumably representing the
// numerator and denominator of a fraction. Each object of type Fraction will have its own
// num and den. Because they are private they cannot be accidentally modified outside the
// definition of Fraction. They are the module's secret.
int num, den;
public:
// This declares a constructor. It uses the default argument notation to actually define
// three constructor syntaxes. Two arguments may be given, one, or zero. Fraction() = 1/2,
// Fraction(x) = x/2, and Fraction(x, y) = x/y. A default denominator of 1 would be more
// normal, especially since this constructor can be used to implicitly convert an int into
// a Fraction.
Fraction(int n = 1, int d = 2) : num(n), den(d) { }
// This function outputs a representation of a Fraction to cout. It repeats the definition
// of operator<< below, which violates the DRY principle so it should probably be written
// as: cout << *this;
void show() {
cout << num << " / " << den; }
// This is an operator overload. It allows you to write, Fraction + Fraction. Note that it
// does not add fractions in the expected way, instead it does a vector addition.
Fraction operator+(Fraction f) const {
return Fraction(num + f.num, den + f.den); }
// Similarly broken.
Fraction operator-(Fraction f) const {
return Fraction(num - f.num, den - f.den); }
// Correct multiplication, although normalizing the fraction is kind of expected.
Fraction operator*(Fraction f) const {
return Fraction(num * f.num, den * f.den); }
// Cannot be bothered to decide if this is correct. Multiplying by the inverse would be the
// more obvious thing to do, like: return *this * Fraction(f.den, f.num);
Fraction operator/(Fraction f) const {
int rNum = (f.den * num) / den;
return Fraction(rNum, f.num); }
// These functions support reading and writing a Fraction using streams. Note that they should
// make use of the out and in parameters, then they would work with all stream types.
friend ostream& operator<<(ostream& out, Fraction& f) {
cout << f.num << " / " << f.den;
return out; }
// The prompts here are poor design.
friend istream& operator>>(istream& in, Fraction& f) {
cout << "\nEnter Numerator: ";
cin >> f.num;
cout << "Enter Denominator: ";
cin >> f.den;
cout << f.num << " / " << f.den;
return in; }
// This function does not do what you would expect based on the name. It returns min(num, den).
// It should be declared const, like operator+ is since it is thread-safe.
int ndMax() {
return (num <= den) ? num : den; }
// This is weird and evil. The intent is to normalize the fraction. Euclid's algorithm would
// be the usual way.
void reduce() {
for (int i = 2; i <= ndMax(); i++)
if (num % i == 0 && den % i == 0) {
num = num / i;
den = den / i;
i = 1; // Evil!!! Do not modify the loop variable in the body of the loop.
} }
// There are a number of other functions, not explicit here, that are implicitly generated
// by the compiler. For example a copy constructor and assignment operator.
};
// This is a simple test driver for the Fraction class.
int main() {
Fraction f1(5, 6);
Fraction f2(80, 1001);
cout << f1 << " and " << f2 << endl;
Fraction f3 = f1 / f2;
f3.reduce();
cout << f3;
cout << endl;
return 0; }

Related

Add fractions using operator overloading

In an interview I was asked to create two classes. The first abstract class is called Number, which supports one operation “+”. And the other one fraction which implements the "Number" abstract class.
Further: For a Fraction once added, it needs to be displayed in its original form. That is, 2/4 has to be displayed as “2/4”, not “1/2” or “0.5”.
No Other detail was provided to me.
Below is what I had tried (Incomplete).
My main.cpp
#include <iostream>
#include "Fraction.h"
using namespace std;
int main()
{
Fraction sumFraction;
Fraction n11(1,2);
Fraction n21(1,2);
cout << n11.getValuenum() << "/";
cout << n11.getValueden() << endl;
cout << n21.getValuenum() << "/";
cout << n21.getValueden() << endl;
sumFraction = n11 + n21;
cout << sumFraction.getValuenum() << endl;
cout << sumFraction.getValueden() << endl;
return 0;
}
My Numbers.h // ABSTRACT CLASS
#pragma once
template<class T>
class Number
{
virtual T& operator= (const T &) = 0; // first parameter is implicitly passed
virtual const T operator+ (const T &) = 0;
virtual void display() = 0;
};
My Fraction.cpp
#include "Fraction.h"
int Fraction::getValuenum()
{
return this->a1;
}
int Fraction::getValueden()
{
return this->a2;
}
Fraction::Fraction()
{
a1 = 0;
a2 = 0;
}
Fraction::Fraction(int num, int den)
{
a1 = num;
a2 = den;
}
void Fraction::display()
{
// will display the number in its original form
}
Fraction& Fraction::operator=(const Fraction &num)
{
a1 = num.a1;
a2 = num.a2;
return *this;
}
const Fraction Fraction::operator+(const Fraction &numberTwo)
{
Fraction n1;
n1.a1 = this->a1*numberTwo.a2 + this->a2*numberTwo.a1;
n1.a2 = this->a2*numberTwo.a2;
return n1;
}
My Fraction.h
#pragma once
#include "Number.h"
class Fraction : public Number<Fraction>
{
private:
int a1;
int a2;
public:
void display();
Fraction();
Fraction(int num, int den);
int getValuenum();
int getValueden();
Fraction& operator= (const Fraction &); // first parameter is implicitly passed
const Fraction operator+ (const Fraction &); // first parameter is implicitly passed
};
Below are my question:
Do I really need to pass numerator and denominator separately from my Main function for each fraction. Currently, I am passing it as separately to keep track of numerator and denominator which might be helpful while adding and returning the result in terms for fraction.
With my operator + logic if I add 1/4+1/4 I get 8/16, what is expected is I guess 2/4 which we get if we add normally. So how to add using numerator and denominator and to keep the fraction in such a way, so that if output is 2/4 then 2/4 and not 1/2 or 0.5.
Please help me.
Some remarks:
you should not allow the denominator to be 0 because it gives an inexistent number (infinity or undeterminated)
you should definitely not initialize the denominator to 0 for same reason (1 seems a more reasonable value)
the correct (mathematical) addition of fractions is (*):
a/b + c/d = (ad +bc)/bd
Instead of (or in addition to) the display method, I would advise you to write a ostream& operator << (ostream&, const Fraction&) overload. That would allow you to just write in you main
std::cout << n11 << " + " << n21 << " = " << sumFraction << std::endl;
I did not really understand you first question, but I would add a conversion from an int:
Fraction(int n): a1(n), a2(1) {};
to allow to write directly Fraction(1, 2) + 1 or Fraction(1) + Fraction(1/2) (the first element of the addition must be a Fraction)
(*) this is the simple and general way. You could also use the least common multiple to get cleaner results:
den = lcm(b,d)
a/b + c/d = (a * den/b) + c * den/d) / den
That way you would get 1/4 + 2/4 = 3/4 instead of 12/16
But computing the LCM is far beyond this answer...

Adding a fractions and classes - Woot

Hey guys to start off I will say that I have looked into a lot of similar programs before posting this question and still need some help. My problem lies in the addition fraction class function where I need to add one fraction to another. I have one class and am currently working with to instances of that class (fractionObject and fractionObject2). I am storing my fractions separately, one in fractionObject and one in fractionObject2. How can I add these in my fraction class function 'Add'?
Any tips will be much appreciated! Thanks for your time!
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
// Regular prototypes
int stringToNumber(const string &Text);
int GCD(int, int);
int LCM(int, int);
class fraction{
public: // Access Specifier
int numerator;
int denominator; // Can never be 0
// Function Prototypes
fraction();
void setNumDen();
void reduce();
void add();
};
// Member functions definitions
fraction::fraction()
{
numerator = 0;
denominator = 0;
}
void fraction::setNumDen()
{
string numString;
string denString;
do{
cout << "Enter a numerator and denominator of fraction 1 separated by whitespace: ";
getline(cin, numString, ' ');
getline(cin, denString);
if (denString == "0")
cout << endl << "Please enter a number that isn't zero." << endl;
} while (denString == "0"); // Making sure denominator is not zero
numerator = stringToNumber(numString);
denominator = stringToNumber(denString);
}
void fraction::reduce()
{
int leastCommonMultiple = 0;
leastCommonMultiple = LCM(numerator, denominator);
numerator /= leastCommonMultiple;
denominator /= leastCommonMultiple;
}
void fraction::add()
{
int leastComDen;
}
int main()
{
fraction fractionObject, fractionObject2;
fractionObject.setNumDen();
fractionObject2.setNumDen();
// Reducing and displaying the reduced fractions
fractionObject.reduce();
fractionObject2.reduce();
cout << "Reduced Fraction 1 = " << fractionObject.numerator << "/" << fractionObject.denominator << "\t" << "Reduced Fraction 2 = " << fractionObject2.numerator << "/" << fractionObject2.denominator << endl;
// Adding and displaying the fractions
system("pause");
return 0;
}
// Function to convert string to number
int stringToNumber(const string &Text)//Text not by const reference so that the function can be used with a
{ //character array as argument
stringstream ss(Text);
int result;
return ss >> result ? result : 0;
}
// result=GCD(a,b)
int LCM(int a, int b) {
int temp = 0;
while (b != 0) {
temp = b;
b = a%b;
a = temp;
}
return a;
}
// result=LCM(a,b);
int GCD(int a, int b) {
int result = 0;
result = a * (b / LCM(a, b));
return result;
}
No complete answer here, but add should have two const fraction& arguments and return a temporary fraction object. You might rename it operator+. Many libraries add a += operator that doesn't require making a temporary object. C++11 allows you to reduce the overhead of these temporary objects with a move constructor.
As for the implementation, here’s a hint: 1/6 + 1/9 = (9+6)/54 = 5/18. I notice you already have a reduce function.

Error: No matching function for call to 'fraction::add(fraction&, fraction&)'

[Error] no matching function for call to 'fraction::add(fraction&, fraction&)'
line 105 which is
f3.add( f1, f2);
This is the error message I'm receiving when I try and compile.
Instance:
I'm trying to create a class of 'fraction' which allows my instructor's pre-set int main() to execute from. I've so far constructed a bare-bones class, and am trying to compile to see if it works.
'My class:
class fraction
{
private:
long num, den;
public:
void setNum(long i_num)
{
num=i_num;
}
void setDen(long)
{
}
long getNum()
{
return num;
}
long getDen()
{
return den;
}
fraction()
{
num = 1;
den = 1;
}
fraction(int n, int d)
{
num = n;
if (d==0)
{
cout << "Cannot divide by zero" << endl;
exit(0); // will terminate the program if division by 0 is attempted
}
else
den = d;
}
fraction add(fraction otherFraction)
{
int n = num*otherFraction.den+otherFraction.num*den;
int d = den*otherFraction.den;
return fraction(n/gcd(n,d),d/gcd(n,d));
}
fraction sub(fraction otherFraction)
{
int n = num*otherFraction.den-otherFraction.num*den;
int d = den*otherFraction.den;
return fraction(n/gcd(n,d),d/gcd(n,d));
}
fraction mult(fraction otherFraction)
{
int n = num*otherFraction.num;
int d = den*otherFraction.den;
return fraction(n/gcd(n,d),d/gcd(n,d));
}
fraction div(fraction otherFraction)
{
int n = num*otherFraction.den;
int d = den*otherFraction.num;
return fraction(n/gcd(n,d),d/gcd(n,d));
}
int gcd(int n, int d)
{
int remainder;
while (d != 0)
{
remainder = n % d;
n = d;
d = remainder;
}
return n;
}
void print() // Display method
{
if (den == 1) // e.g. fraction 2/1 will display simply as 2
cout << num << endl;
else
cout << num << "/" << den << endl;
}
};'
My instructor's int main():
int main ( )
{ // define seven instances of the class fraction
fraction f1, f2, f3, f4, f5, f6, f7;
//set values for the numerator and denominator to f1 and print
//them
f1.setDen( 2L);
f1.setNum( 0L);
f1.print();
//set values for the numerator and denominator to f2 and print them
f2.setDen( 4L);
f2.setNum( 3L);
f2.print();
f3.add( f1, f2);
f3.print();
f4.sub( f1, f2);
f4.print();
f5.mult( f1, f2);
f5.print();
f6.div( f1, f2);
f6.print();
f7.inc(f1);
f7.print(f1);
My instructor informed us not to edit main() in any way.
I've traced it back to the method in the class
fraction add(fraction otherFraction)
{
int n = num*otherFraction.den+otherFraction.num*den;
int d = den*otherFraction.den;
return fraction(n/gcd(n,d),d/gcd(n,d));
}
How do I go about passing the variables in main() so they'll work in the class?
I've only been taught one way of doing things, and this is my first Object Oriented class. He's teaching different ways of organizing and I'm not understanding it. He's yet to e-mail me back with help about a week now (online class).
Any hints/tips would be much appreciated.
Thank you.
as you can see from the error reported, the compiler looks for a method with the following signature:
fraction::add(fraction&, fraction&)
while the method that you have defined have the following one:
fraction::add(fraction&)
so, you are missing an argument (another fraction).
I'm not quite sure about the meaning of the 'add' method (the way your instructor calls it) but I think it's about assigning the result of the sum of the two fraction to the one on which you are calling the object, that is f3 = f1 +f2. In that case you should implement you add like this:
void add(const fraction& a,const fraction& b)
{
int n = a.getNum()*b.getDen()+b.getNum()*a.getDen();
int d = a.getDen()*b.getDen();
num = n/gcd(n,d);
dem = d/gcd(n,d);
}
more or less..:)
PS: I added some 'const francion&' just as an optimization to avoid copying the arguments each time you call the function. It's not strictly necessary but it's a very good programming practice..;)
Compare the prototype of your function:
fraction add(fraction otherFraction)
with the way the main calls it:
f3.add( f1, f2);
Do you see the mismatch? Your function takes one parameter, but main() calls it with two arguments. You need to add an extra parameter to your function.
I believe the intended semantics for f3.add(f1, f2) is f3 = f1 + f2.
add() is a member function that takes one fraction parameter. But since it's being called on an instance of fraction, you'll be adding two objects, otherFraction and *this. *this is the instance of the object on which add() is being called, and otherFraction is the argument passed to add():
f1.add(f2);
^ ^
| |
---- -------------
*this otherFraction
All you need to do is assign the result to f3:
f3 = f1.add(f2);

Redefinition of class in CPP File Error

I know there are plenty of questions like these, but I couldn't find a solution that worked for me.
Okay, I am trying to make simple fraction calculator than can add or subtract any number of functions and write the answer as a reduced fraction.
Example: input=
3/2 + 4/
8
, output =
2
I am trying overload operators in order to accomplish this.
So in the program, I am trying to develop the input consists of an expression made of fractions separated by the operators '+'or '-'.
The number of fractions in the expression is arbitrary.
Each of the following 6 lines is an example of valid input expression:
1/2 + 3/4
1/2 -5/7+3/5
355/113
3 /9-21/ -7
4/7-5/-8
-2/-3+7/5
The problem that I am having is that in when I run my Main CPP program it has a class redefinition error:
fraction.cpp:6:7: error: redefinition of 'Fraction'
class Fraction
^
./Fraction.h:7:7: note: previous definition is here
class Fraction{
However, that should not be a problem because I declared the class and member functions in my header files and defined them in my CPP file.
My following code is below:
Header File
#ifndef FRACTION_H
#define FRACTION_H
#include <iostream>
using namespace std;
class Fraction{
public:
Fraction(int , int );
int fraction(int,int);
void reduce_fraction(int *, int *);
Fraction& operator+(const Fraction& n);
Fraction& operator-(const Fraction& n);
friend ostream& operator<<(ostream &os, const Fraction& n);
friend istream& operator>>(istream &is, const Fraction& n);
};
#endif
CPP File
#include <iostream>
using namespace std;
#include "Fraction.h"
#include <stdexcept>
class Fraction
{
public:
Fraction::Fraction(int a, int b);
int find_gcd(int n1, int n2);
void reduce_fraction(int *nump, int *denomp)
{
int gcd;
gcd = find_gcd(*nump, *denomp);
*nump = *nump / gcd;
*denomp = *denomp / gcd;
if ((*denomp<0 && *nump < 0 ))
{
*denomp*=-1;
*nump*=-1;
}
else if (*denomp < 0 && *nump >0){
*denomp*=-1;
}
if ( *denomp ==0) {
throw invalid_argument( "Error: zero denominator" );
}
}
Fraction& Fraction::operator+(const Fraction& n) {
int denom = *denomp * n.denom;
int numera = (*nump * n.numera) + (n.denom * n.nump);
return Fraction(numera,denom);
}
Fraction& Fraction::operator-(const Fraction& n) {
int denom = *denomp * n.denom;
int numera = (*nump * n.numera) - (n.denom* n.nump);
return Fraction(numera, denom);
}
friend ostream& operator<<(ostream &os, Fraction& n)
{
if (n.numera == 0)
{
cout << 0 << endl;
return os;
}
else if (n.numera == n.denom)
{
cout << 1 << endl;
return os
}
else
{
cout << n.numera << '/' << n.denom << endl;
return os;
}
}
friend istream& operator>>(istream &os, Fraction& n)
{
char slash = 0;
return is >> n.numera >> slash >> n.denom;
}
};
#include <iostream>
using namespace std;
#include "Fraction.h"
#include <stdexcept>
class Fraction
{
public:
Fraction::Fraction(int a, int b);
int find_gcd(int n1, int n2);
void reduce_fraction(int *nump, int *denomp)
{
int gcd;
gcd = find_gcd(*nump, *denomp);
*nump = *nump / gcd;
*denomp = *denomp / gcd;
if ((*denomp<0 && *nump < 0 ))
{
*denomp*=-1;
*nump*=-1;
}
else if (*denomp < 0 && *nump >0){
*denomp*=-1;
}
if ( *denomp ==0) {
throw invalid_argument( "Error: zero denominator" );
}
}
Fraction& Fraction::operator+(const Fraction& n) {
int denom = *denomp * n.denom;
int numera = (*nump * n.numera) + (n.denom * n.nump);
return Fraction(numera,denom);
}
Fraction& Fraction::operator-(const Fraction& n) {
int denom = *denomp * n.denom;
int numera = (*nump * n.numera) - (n.denom* n.nump);
return Fraction(numera, denom);
}
friend ostream& operator<<(ostream &os, Fraction& n)
{
if (n.numera == 0)
{
cout << 0 << endl;
return os;
}
else if (n.numera == n.denom)
{
cout << 1 << endl;
return os
}
else
{
cout << n.numera << '/' << n.denom << endl;
return os;
}
}
friend istream& operator>>(istream &os, Fraction& n)
{
char slash = 0;
return is >> n.numera >> slash >> n.denom;
}
};
MAIN CPP FILE
#include "Fraction.h"
#include <iostream>
using namespace std;
int main()
{
Fraction x(2,3);
Fraction y(6,-2);
cout << x << endl;
cout << y << endl;
cin >> y;
cout << y << endl;
Fraction z = x + y;
cout << x << " + " << y << " = " << z << endl;
}
I am essentially having trouble with understanding why I am getting the previous definition error and how exactly to fix it. Also, if you see anything else wrong with my implementation in this program I would appreciate you telling me!
Thank you very much!
The way to define member functions in Fraction.cpp is not like this:
class Fraction
{
public:
void reduce_fraction(int *nump, int *denomp)
{
...
}
}
but rather like this:
void Fraction::reduce_fraction(int *nump, int *denomp)
{
...
}
More generally, you should not write this much code before testing any of it.

calculate polynomial with coefficients as abstract class Number

I am struggling with adding operations of classes Natural, Rational, Complex that represent appropriate math objects. I need that to calculate polynomial in x.
All classes inherit abstract class Number. Having all coefficients in an array of Numbers I want to calculate the polynomial. To do so I need operation of multiplying by double (x is double). x gets transformed into Rational and multiplied. This works fine. My problem is how to add classes of abstract type Number?
I can't make it work. All I get is never ending recursion in Number::add(Number) (it invokes itself instead of invoking others methods for types Natural, Rational, Complex).
#include
#include
#include
#include
#include
#include
#include
using namespace std;
class Natural;class Rational;class Complex;
class Number {
public:
virtual string toString() const = 0;
virtual Number *operator*(const Rational) const = 0;
virtual Number *add(const Natural*) const = 0;
virtual Number *add(const Rational*) const = 0;
virtual Number *add(const Complex*) const = 0;
virtual Number *add(const Number *n) const {
n->add(this);
}
};
class Natural : public Number {
friend class Complex;
int n;
public:
Natural(const Natural &s) {
n = s.n;
}
Natural(int number) : n(number) {}
string toString() const {
stringstream ss;
ss << n;
return ss.str();
}
operator Rational() const;
operator Complex() const;
operator int() const {
return n;
}
Number *operator*(const Rational r) const;
Number *add(const Natural* number) const {
return new Natural(n + number->n);
}
Number *add(const Rational*) const;
Number *add(const Complex*) const;
};
class Rational : public Number {
friend class Natural;
int numerator, denominator;
void divideByGCD() {
int a = numerator, b = denominator;
//cout << a << ' ' << b << ' ';
if(a < b) {
int temp = a;
a = b;
b = temp;
}
while (b > 0) {
int r = a % b;
a = b; b = r;
//cout << r << endl;
}
numerator /= a;
denominator /= a;
//cout << a << endl;
}
public:
Rational() {}
Rational(const Rational &s) {
numerator = s.numerator;
denominator = s.denominator;
}
Rational(int n, int d) {
if(d == 0) throw new runtime_error("denominator equals 0");
if(d < 0) {
numerator = -n;
denominator = -d;
} else {
numerator = n;
denominator = d;
}
divideByGCD();
}
Rational(double d) {
int i = 0, mul = 1;
int r = d-floor(d);;
while(r!=0) {
i++; mul *= 10;
r = 10*r-floor(10*r);
}
numerator = (int)mul*d;
denominator = mul;
divideByGCD();
}
string toString() const {
stringstream ss;
ss << numerator;
if(denominator > 1) ss << '/' << denominator;
return ss.str();
}
operator const Complex() const;
operator const double() const {
return (double)numerator/denominator;
}
Number *operator*(const Rational r) const {
return new Rational(numerator*r.numerator, denominator*r.denominator);
}
Number *add(const Rational* r) const {
return new Rational(numerator*r->denominator+r->numerator*denominator, denominator*r->denominator);
}
Number *add(const Natural*) const;
Number *add(const Complex*) const;
};
class Complex : public Number {
friend class Rational;
double real, imaginary;
static const double radius = 10;
public:
Complex() {}
Complex(const Complex &s) {
real = s.real;
imaginary = s.imaginary;
}
Complex(const double r, const double im) : real(r), imaginary(im) {}
string toString() const {
stringstream ss;
ss << real;
if(imaginary != 0) ss << '+' << imaginary << 'i';
return ss.str();
}
Number *operator*(const Rational r) const;
Number *add(const Complex* c) const {
return new Complex(real + c->real, imaginary + c->imaginary);
}
Number *add(const Natural*) const;
Number *add(const Rational*) const;
};
Natural::operator Rational() const {
return Rational(n,1);
}
Natural::operator Complex() const {
return Complex(n, 0);
}
Rational::operator const Complex() const {
return Complex((double)numerator/denominator, 0);
}
Number *Natural::operator*(const Rational r) const {
return new Rational(n*r.numerator, r.denominator);
}
Number *Complex::operator*(const Rational r) const {
return new Complex(real*(double)r, imaginary*(double)r);
}
Number *Natural::add(const Rational *r) const {
if(r->denominator == 1) return new Natural(n+r->numerator);
else return new Rational(n*r->denominator,r->denominator);
}
Number *Natural::add(const Complex *c) const {
return c->add(this);
}
Number *Rational::add(const Natural *n) const {
return n->add(this);
}
Number *Rational::add(const Complex *c) const {
return new Complex(c->real+(double)*this, c->imaginary);
}
Number *Complex::add(const Natural *number) const {
return new Complex(real+number->n, imaginary);
}
Number *Complex::add(const Rational *r) const {
return r->add(this);
}
Number *poly(double x, Number *a[], unsigned int size) {
if(size == 1) return a[0];
else return a[0]->add((*poly(x, a+1, size-1))*Rational(x));
}
int main() {
cout << (Natural(5)*(Rational)2.0)->toString() << endl;
Number *coefs[] = {new Natural(5), new Natural(6)};
cout << poly(2, coefs, 2) << endl;
}
How should I fix Number::add(Number) so that while invoking add on object of type Number program itself figure out which of virtual method add to choose?
This is known as multi-dispatch. Here are some links to look at
Multiple_dispatch
best multimethods implementation
I think the problem is:
virtual Number *add(const Number *n) const {
n->add(this);
}
If you multiply a Rational by a Natural that is stored in a Number *, it can't polymorphicly upcast the Number * to a Natural *. I agree w/g-makulik in that references/values make a lot more sense here, as you are leaking memory all over the place. Remove support for Number + Number. Also, if I add a Natural and a Rational together, I get a Number * back, but what kind of number is it? I think the architecture needs a bit more thought; I might get rid of the base class pure virtual methods entirely (except maybe toString). For example:
class Number
{
public:
virtual string toString() = 0;
};
class Rational : public Number
{
string toString() {...}
// forget 'add', use operators
Rational operator+(const Rational & _rhs) const {Rational ret; ...; return ret;}
Rational & operator+=(const Rational & _rhs) const {...; return *this;}
...
}
Edit
For a quick fix, I think you just need to get rid of virtual Number *operator*(const Rational) const = 0;, and replace it with a version for each sub-class (e.x., Rational * operator*(const Natural) const)
Or, add an enumerated member variable to Number to keep track of the type:
enum Type { NATURAL, RATIONAL, ...}
Type mType;
or use RTTI, such that you can selectively choose the right add method in Number::add:
Number * add(Number * _rhs)
{
if(_rhs->mType == RATIONAL)
return this->add((Rational *)_rhs);
...
}
it looks kinda sloppy, but it will work
it looks like Visitor pattern is what I've been looking for. I wanted to have functions accept and visit in the same class. I believe my mistake was to give them the same name.