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.
Related
This is part of my polynomial.cpp to get terms by overloading istream
void Newterm(float coef, int deg) {
if (terms == capacity) {
capacity *= 2;
Term* tmp = new Term[capacity];
copy(termArray, termArray + terms, tmp);
termArray = tmp;
delete[] tmp;
}
termArray[terms].degree = deg;
termArray[terms++].coef = coef;
}
friend istream& operator >> (istream& is, Polynomial& pl) {
cout << "number of terms : ";
int t; is >> t;
cout << endl;
float coeff;
int degree;
for (int i = 0; i < t;i++) {
cout << i + 1 << "'s term: ";
is >> coeff >> degree;
pl.Newterm(coeff, degree);
}
return is;
};
of course, i tried to figure out whaaat made this result..
tried:
removing 'for' loop
this actually worked.. but it only works when terms=1
firstly creating term and input data
Newterm(0,0);
is>>pl.termArray[i].coef>>pl.termArray[i].degree;
it couldn't fix anything...
so i think it has to do with loops..
but whyyyy?
Using std::vector instead of doing your own memory managment
(why reinvent the wheel if there is a tested solution in the standard library)
#include <iostream>
#include <vector>
struct Term final
{
Term() = default;
~Term() = default;
Term(int d, double c) :
degree{ d },
coef{ c }
{
}
int degree{ 0 };
double coef{ 1.0 };
};
class Polynomial final
{
public:
Polynomial() = default;
~Polynomial() = default;
explicit Polynomial(const std::initializer_list<Term> terms) :
m_terms{ terms }
{
}
void add(const Term& term)
{
m_terms.push_back(term);
}
private:
std::vector<Term> m_terms;
};
std::istream& operator>>(std::istream& is, Polynomial& polynomial)
{
std::size_t n{ 0 }; // indices are not ints the can't be < 0
is >> n;
for (std::size_t i = 0; i < n; ++i)
{
Term term{};
is >> term.coef;
is >> term.degree;
polynomial.add(term);
}
return is;
}
int main()
{
// to show you that std::vector can handle all the memory managment for you
// constructor with an initializer list that adds 3 terms
// that's also why the Term has a constructor, it is to make it work with
// initializer list
Polynomial p{ { 1,2.0 }, { 2,4.0 }, { 1,-1.0 } };
}
I created a code by using operator overloading concept in c++ for addition of two rational numbers by overloading the +(plus) and the <<(Insertion) operator and I am not able to get a function being accessed from the scope of operator overloading of + operator. How to access the LCM() function from the scope of operator+ overloaded?
I tried using the friend function to access my LCM() function from within the scope of operator+ overloaded function but it didn't work!
#include <iostream>
using namespace std;
class Rational {
private:
int num, den;
public:
int getnum()
{
return this->num;
}
int getden()
{
return this->den;
}
Rational(int num = 0, int den = 0)
{
this->num = num;
this->den = den;
}
int LCM(int a, int b);
friend ostream& operator<<(ostream& out, Rational& r);
friend Rational operator+(Rational x, Rational y);
};
int Rational::LCM(int a, int b)
{
int i = a > b ? a : b;
for (i; i <= a * b; i++) {
if (i % a == 0 && i % b == 0) {
break;
}
}
return i;
}
ostream& operator<<(ostream& out, Rational& r)
{
out << r.getnum() << "/" << r.getden();
return out;
}
Rational operator+(Rational x, Rational y)
{
Rational temp;
int temp1;
int div;
temp1 = LCM(x.den, y.den);
temp.num = (int(temp1 / x.den) * x.num) + (int(temp1 / y.den) * y.num);
temp.den = temp1;
return temp;
}
int main()
{
Rational r1(3, 2);
Rational r2(9, 4);
Rational r3;
r3 = r1 + r2;
cout << r3;
return 0;
}
And I get the error:
error: ‘LCM’ was not declared in this scope
I would say that int Rational::LCM(int a,int b) does not really have anything to do with the Rational class and should probably be a utility function (non-member function), then you would be able to use it anywhere
I am a beginner in C++. I am learning on how to overload operators. I have created a class Complex that represents complex numbers and methods for complex arithmetic and a class ComplexArray that represents fixed-length arrays of elements in complex vector space C.
I get compiler errors, that it is unable to find the correct form of operator[]. However, I searched the internet and I am unable to rectify the error. Any hints/tips in the right direction would be of tremendous help.
Severity Code Description Project File Line Suppression State
Error C2676 binary '[': 'const ComplexArray' does not define this operator or a conversion to a type acceptable to the predefined operator ComplexArrays c:\users\quasa\source\repos\complexarrays\complexarrays\testcomplexarray.cpp 7
Here is my code:
TestComplexArray.cpp
#include <iostream>
#include "ComplexArray.h"
Complex ComplexSum(const ComplexArray& cArray, int size)
{
Complex sum = cArray[0];
for (int i = 1; i < size; i++)
{
sum = sum + cArray[i];
}
return sum;
}
Complex ComplexProduct(const ComplexArray& cArray, int size)
{
Complex product = cArray[0];
for (int j = 1; j < size; j++)
{
product = product * cArray[j];
}
return product;
}
int main()
{
char ch;
const int size = 5;
ComplexArray cArray(size);
for (int i = 0; i < size; i++)
{
cArray[i] = Complex((double)(i + 1), 0);
std::cout << cArray[i];
}
Complex sum = ComplexSum(cArray, size);
Complex product = ComplexProduct(cArray, size);
std::cout << "Sum = " << sum << std::endl;
std::cout << "Product = " << product << std::endl;
std::cin >> ch;
return 0;
}
ComplexArray.h
class ComplexArray
{
private:
Complex* complexArr;
int size;
ComplexArray();
public:
//Constructors and destructors
ComplexArray(int size);
ComplexArray(const ComplexArray& source);
virtual ~ComplexArray();
//Range for the complexArr
int MaxIndex() const;
//Overload the indexing operator
const Complex& operator [](int index) const;
Complex& operator [](int index);
};
ComplexArray.cpp
#include "Complex.h"
#include "ComplexArray.h"
ComplexArray::ComplexArray(int s)
{
size = s;
complexArr = new Complex[size];
}
ComplexArray::ComplexArray(const ComplexArray& source)
{
//Deep copy source
size = source.size;
complexArr = new Complex[size];
for (int i = 0; i < size; i++)
{
complexArr[i] = source.complexArr[i];
}
}
ComplexArray::~ComplexArray()
{
delete[] complexArr;
}
int ComplexArray::MaxIndex() const
{
return (size - 1);
}
/*
c1.operator[](int index) should return a reference to the Complex
object, because there are two possible cases.
Case 1:
Complex c = complexArray[3];
Case 2:
complexArray[3] = c;
In the second case, complexArray[3] is an lvalue, so it must return
a Complex object by reference, so that it can be assigned to.
*/
const Complex& ComplexArray::operator[] (int index) const
{
return complexArr[index];
}
Complex& ComplexArray::operator[](int index)
{
return complexArr[index];
}
Complex.h
#include <iostream>
class Complex
{
private:
double x;
double y;
void init(double xs, double ys); //Private helper function
public:
//Constructors and destructors
Complex();
Complex(const Complex& z);
Complex(double xs, double ys);
virtual ~Complex();
//Selectors
double X() const;
double Y() const;
//Modifiers
void X(double xs);
void Y(double ys);
//Overload binary +, = and * operators
Complex operator + (const Complex& z);
Complex& operator = (const Complex& z);
Complex operator * (const Complex& z) const;
//Overload unary - operator
Complex operator -() const;
friend Complex operator * (const double alpha, const Complex& z);
friend Complex operator * (const Complex& z, const double beta);
//Overload << operator
friend std::ostream& operator << (std::ostream& os, const Complex& z);
//A complex function f(z)=z^2
Complex square();
};
As you have all pointed out - I was missing the forward definition of a #include.
Complex.cpp has the header
#include "Complex.h"
ComplexArray.h has the header
#include "Complex.h"
ComplexArray.cpp has the header
#include "ComplexArray.h"
TestComplexNumbers.cpp has the header
#include <iostream>
#include "ComplexArray.h"
My compile-time errors have been resolved.
I don't think the error comes from operator[], as you can see in the function:
Complex ComplexSum(const ComplexArray& cArray, int size)
{
Complex sum = cArray[0];
for (int i = 1; i < cArray.MaxIndex(); i++)
{
sum = sum + cArray[i];
}
}
You don't return a result. That's fatal.
ComplexArray depends on Complex but order of includes doesn't look right
#include "ComplexArray.h"
#include "Complex.h"
You have to forward-declare Complex before ComplexArray
class Complex;
Code fails at \testcomplexarray.cpp line 7 which is
Complex sum = cArray[0];
It looks like you have problem with ctors of Complex. Be sure that you have NOT defined such:
Complex(Complex& v); // that's bad. it prevents to use copy constructor
If you need copy ctor for some inconceivable reason, it always should look so:
Complex(const Complex& v);
So I created a class called myClass that takes in an int and has a private variable that stores the int as a vector in binary (i.e. 12 is '1100'). I want to define an operator that adds two myClass variables together as a vector of bools (aka bit-wise operation).
Here is the code I have:
class myClass {
public:
myClass();
myClass(int a);
myClass& operator+(const myClass& value);
private:
std::vector<bool> bit;
};
I want this to work in the main function:
int main() {
std::cin >> value;
Integer a = value;
std::cin >> value;
Integer b = value;
myClass c = a+b;
return 0;
}
Operator definition:
myClass myClass::operator+(const myClass& rhs) {
Integer c = // not sure what to do here
return c;
}
The part that's confusing me is that it must take in an integer but then the operator does the operation on the vector of bools.
Well obviously you need to do the same as when you add normal numbers on paper. Start with the lowest significance bits, and add them together. If the result overflows (eg. binary 1+1=10) then remember that overflow for the next iteration.
I'd strongly suggest that you first create constructor that takes bool array for your class:
myClass(std::vector<bool> bits);
We'll use that in the implementation. Now what you want is to add the lists of bools. I have created an implementation that doesn't care how big the lists are. This will be handy if you want to calculate with huge integers:
#include <vector>
bool add_bools(const bool A, const bool B) {
return !(A && B) && (A || B);
}
/** Loops over vectors and adds the booleans in them
the booleans are considered to be in little endian order
so that the least significant is first in the array. **/
std::vector<bool> add_vectors(const std::vector<bool>& first,
const std::vector<bool>& second) {
std::vector<bool> result;
// Remembers that previous addition produced false when
// we add true+true
bool overflow = false;
const int bits = first.size()>second.size()?first.size():second.size();
for (int i = 0; i < bits || overflow; ++i) {
bool bitA, bitB;
bitA = i<first.size() ? first[i]:false;
bitB = i<second.size() ? second[i]:false;
bool tmp_result = add_bools(bitA, bitB);
// remember to add overflow from previous iteration
result.push_back(add_bools(tmp_result, overflow));
// remember overflow for next iteration
overflow = (bitA&&bitB) || (overflow && tmp_result);
}
return result;
}
#include <iostream>
void test_add_vectors() {
std::vector<bool> first;
std::vector<bool> second;
const int bits = 5;
for (int i = 0, l = bits; i < l; ++i) {
first.push_back(false);
second.push_back(true);
}
first[0] = true;
std::vector<bool> result = add_vectors(first, second);
for (int i = 0, l = result.size(); i < l; ++i) {
std::cout<< (result[i]?'1':'0')<<" ";
}
}
You can use that implementation like this, making use of the constructor that takes bool array:
myClass myClass::operator+(const myClass& rhs) {
myClass result(add_vectors(bit, rhs.bit));
return result;
}
You need to define a way to go to and from an integer representation. Here's a rough idea:
#include <vector>
#include <iostream>
class myClass {
private:
void setInt(int x) {
bit.clear();
while (x) {
if (x & 1)
bit.push_back(1);
else
bit.push_back(0);
x>>=1;
}
reverse(bit.begin(), bit.end());
}
public:
int toInt() const {
int i = 0;
for (size_t b = 0; b < bit.size(); b++) {
if (bit[bit.size() - 1 - b])
i |= 1<<b;
}
return i;
}
myClass(int a) {
setInt(a);
}
myClass& operator+(const myClass& value) {
setInt(toInt() + value.toInt());
return *this;
}
private:
std::vector<bool> bit;
};
int main() {
myClass c(10);
myClass d(20);
std::cout << "c=" << c.toInt() << "\n";
std::cout << "d=" << d.toInt() << "\n";
std::cout << "Sum=" << (c + d).toInt() << "\n";
}
`myClass c = a+b;`
Since a and b are both declared as Integer, this line will call operator+(const Integer& x, const Integer& y) or Integer::operator+(const Integer& x). The only way it will call myClass::operator+(const myClass& rhs) is if you have a conversion constructor myClass::myClass(const Integer& i).
I have been trying to overload the + operator with 2 custom classes Fraction and Integer. I'd ideally like the + operator to return the simplest version of the operation (i.e. 1/4 + 3/4 == 1 (Integer) ). I haven't found a good way to dynamically assign the return type, so I've tried to return multiple values enclosed in a Struct or tuple. I encouter a segfault when actually attempting the operation in main as follows:
///main/////////
int main(){
Fraction *f = new Fraction(1,4);
Fraction *f2 = new Fraction(3,4);
Fraction *resF = new Fraction();//results
Integer *resI = new Integer();
boost::tie(resF, resI) = *f+*f2; //SEGFAULT here
}
The two classes involved are deriviatives of a common abstract base class, with members and functions defined here:
#include <boost/tuple/tuple.hpp>
#include <iostream>
//Number class
//forward declarations for tuple
class Integer;
class Fraction;
//abstract base class
template<class T>//T is derived class
class Number{
virtual const boost::tuple<Fraction*, Integer*> operator+ (const Number&) {};
virtual void display(std::ostream &) const {} ;
virtual bool operator==(const Number& rhs) const{} ;
};//end of Number class
//Integer class
class Integer: public Number<Integer>{
int numericValue;//<! the value of the integer
public:
int getValue() const;//<!access private member variable numericValue
void setValue(int);//<!set private member variable numericValue
Integer();//<!default constructor
Integer(int);//<!param constructor
virtual ~Integer() {}//<!destructor
//display
void display(std::ostream &) const;//<!stream a display of the number
//int == int
bool operator==(const Integer&) const;//<! comparator int-int
// int + int
const Integer operator+ (const Integer &);//<! add int+int
};
//DEFINITIONS////////////////////
//Default constructor
Integer::Integer(){
numericValue = 0;
}
// param constructor
Integer::Integer(int num){
numericValue = num;
}
//get integer value
int Integer::getValue() const{
return this->numericValue;
}
//set integer value
void Integer::setValue(int x){
this->numericValue = x;
}
//display int
void Integer::display(std::ostream& stream) const{
stream << this->numericValue<<std::endl;
}
// int + int
const Integer Integer::operator+(const Integer &rhs){
Integer temp = this->numericValue + rhs.numericValue;
return temp;
}
// int == int
bool Integer::operator==(const Integer& rhs) const{
if(this->numericValue == rhs.numericValue)
return true;
else
return false;
}
//end of Integer class
//Fraction class
class Fraction: public Number<Fraction>{
Integer numerator;
Integer denominator;
boost::tuple<Fraction*, Integer*> resOfAdd;
public:
int getNumerator();//<! to access private member
int getDenominator();//<! to access private member
bool isInteger;//<! flag if the fraction result of '+' can be reduced as an integer
bool isWhole();//!<tells if can be simplified to integer
Integer fToI;//<! store the integer value of the fraction if it is whole
Fraction() = default;//<! default constructor
Fraction(const int &, const int &);//<!param constructor
const Fraction simplify(const Fraction &in);//<! simplifies fraction if possible
int gcdCalculate(int lhs, int rhs);//!<greatest common denominator
int lcmCalculate(const int lhs, const int rhs);//<!least common
virtual ~Fraction() {}
//display
void display(std::ostream &) const;
// frac == frac
bool operator==(const Fraction& rhs) const;
//frac + frac
boost::tuple<Fraction*, Integer*> operator+(const Fraction &);
};//end of Fraction class
//DEFINITIONS///////////////////
// param constructor
Fraction::Fraction(const int & num, const int & den){
numerator.setValue(num);
denominator.setValue(den);
if(denominator.getValue()==1){//also an integer
fToI = Integer(numerator.getValue());
}
if(denominator.getValue() < 0 && numerator.getValue() > 0){//negative sign on bottom
denominator.setValue(denominator.getValue()*-1);
numerator.setValue(numerator.getValue()*-1); //switch it to the top
}
if(denominator.getValue() < 0 && numerator.getValue() < 0){//both top and bottom are negative
denominator.setValue(denominator.getValue()*-1);
numerator.setValue(numerator.getValue()*-1); //flip them to positive
}
}
//get ifInteger
bool Fraction::isWhole(){
return this->isInteger;
}
//get numerator
int Fraction::getNumerator(){
return this->numerator.getValue();
}
//get denominator
int Fraction::getDenominator(){
return this->denominator.getValue();
}
// display the fraction value
void Fraction::display(std::ostream & stream) const{
stream << this->numerator.getValue() << "/" << this->denominator.getValue()<<std::endl;
}
//simplify fraction
const Fraction Fraction::simplify(const Fraction &in){
int gcd = gcdCalculate(in.numerator.getValue(), in.denominator.getValue());
Fraction res = Fraction(in.numerator.getValue()/gcd, in.denominator.getValue()/gcd);
return res;
}
//lcm - least common multiplier
int Fraction::lcmCalculate(const int lhs, const int rhs){
int temp = gcdCalculate(lhs, rhs);
return temp ? (lhs / temp * rhs) : 0;
}
//gcd - greatest common divisor
int Fraction::gcdCalculate(int a, int b){
return b == 0 ? a : gcdCalculate(b, a % b);
}
//frac + frac -- causing problem
boost::tuple<Fraction*, Integer*>/*numRep<Fraction, Integer>*/ Fraction::operator+(const Fraction &rhsIn){
int numRes, denRes;
Fraction* resF;
Integer* resI; //if there is an integer result
//simplify input
Fraction lhs = simplify(*this);
Fraction rhs = simplify(rhsIn);
int lcm = lcmCalculate(lhs.denominator.getValue(), rhs.denominator.getValue());
int gcd = gcdCalculate(lhs.denominator.getValue(), rhs.denominator.getValue());
//share denominator?
if(lhs.denominator.getValue() == rhs.denominator.getValue()){
numRes = lhs.numerator.getValue() + rhs.numerator.getValue();//simply add the numerators
denRes = lhs.denominator.getValue();//keep denominator
}
else{
// a1 a2 a1*b2+a2*b1
// -- + -- = -----------
// b1 b2 b1*b2
int a1 = lhs.getNumerator();
int b1 = lhs.getDenominator();
int a2 = rhs.numerator.getValue();
int b2 = rhs.denominator.getValue();
numRes = a1*b2 + a2*b1;
denRes = b1*b2;
}
*resF = Fraction(numRes, denRes);
//simplify
*resF = simplify(*resF);
if(resF->denominator.getValue() == 1){//integer result
resF->isInteger = true;//flag
fToI = Integer(resF->numerator.getValue());//make Integer
resI = &fToI; //return the integer when you can
}
else{
resI = new Integer(0);
}
//put the fraction and the (possible) integer representations into a number struct
resOfAdd = boost::make_tuple(resF, resI);
std::cout<<" + = ";
resF->display(std::cout);
delete resF;
delete resI;
return resOfAdd;
}
I must be doing something wrong to get the same segfault error using both a struct and tuple. Could anyone advise on my mistake, or suggest an alternate/superior solution to assign the return value dynamically? I understand that dynamically flexible return types may not be possible. Thank you for your time and help.
Fraction* resf;
...
*resf =
resf is an uninitialized pointer, and you are trying to copy-assign something to the location it points to.
Returning a pointer here is a bad idea because it introduces ownership semantics. Just return by value:
boost::tuple<Fraction, Integer> ...
If you were using pointers so you could indicate whether the integer was present or not, consider using boost::optional.