Thread: Inheritance problems

  1. #1
    Registered User
    Join Date
    Dec 2010
    Posts
    14

    Inheritance problems

    I am working with fraction classes in a book, I have run into a problem I cant seem to get around, I was going to read through and skip the examples, but it appears the last few chapters all deal with this class.

    The idea is getting operators to work on a subclass, which according to the book, the goal is to provide constructors for converting items back and forth.

    The main class if Fraction, and the subclass is FloatFraction. Fraction is constructed from integers as numerator and denominator, and it has functions for handle operator user for +,-,*,/.

    Now I want to be able to use the operators on float fractions, which are constructed as either 2 integers, or a double.

    When constructed with a double of say 1.34, it would produce a fraction of 134/100.

    I know from previous chapters dealing with just the Fraction class that the operators all work as expected.

    Something is wrong with the example code and I can't seem to figure it out, it's been a couple of hours and I haven't been successful.

    Heres the code for the two classes, The Fraction class is modified from the book to add *, and / operators. But I am posting the FloatFraction class directly from the source cd.

    Code:
    #include <iostream>
    using namespace std;
    
    class Fraction
    {
        private:
            int num, den;  //numerator and denominator
    
        public:
            void set(int n, int d)
            {
                num = n;
                den = d;
                normalize();
            }
            int get_num()
            {
                return num;
            }
            int get_den()
            {
                return den;
            }
            Fraction()
            {
                set(0, 1);
            }
            Fraction(int n, int d)
            {
                num = n;
                den = d;
                normalize();
            }
            Fraction(int n)
            {
                set(n, 1);
            }
            Fraction(Fraction const &src)
            {
                num = src.num;
                den = src.den;
            }
            Fraction add(const Fraction &other);
            Fraction mult(const Fraction &other);
            Fraction div(const Fraction &other);
            Fraction sub(const Fraction &other);
            bool operator>(const Fraction &other);
            bool operator<(const Fraction &other);
            bool operator==(const Fraction &other)
            {
                return(num == other.num && den == other.den);
            }
            Fraction operator+=(const Fraction &fract)
            {
                return add(fract);
            }
            Fraction operator+(const Fraction &fract)
            {
                return add(fract);
            }
            Fraction operator*(const Fraction &fract)
            {
                return mult(fract);
            }
            Fraction operator/(const Fraction &fract)
            {
                return div(fract);
            }
            Fraction operator-(const Fraction &fract)
            {
                return sub(fract);
            }
            friend ostream &operator<<(ostream &os, Fraction &fr);
    
            //friend ostream &operator>>(ostream &os, Fraction &fr);
        private:
            void normalize();  //put fraction into standard form
            int gcf(int a, int b);
            int lcm(int a, int b);
    };
    
    
    #include <iostream>
    #include <stdlib.h>
    using namespace std;
    
    
    ostream &operator<<(ostream &os, Fraction &fr)
    {
        os << "(" << fr.num << "/" << fr.den << ")";
        return os;
    }
    
    bool Fraction::operator>(const Fraction &other)
    {
        if(num * other.den > den * other.num)
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }
    
    bool Fraction::operator<(const Fraction &other)
    {
        if(num * other.den < den * other.num)
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }
    
    
    Fraction Fraction::div(const Fraction &other)
    {
        Fraction f1, f2, f3;
    
        f1.set(num, den);
        f2.set(other.den, other.num);
    
        f3 = f1.mult(f2);
        f3.set(f3.den, f3.num);
        return f3;
    }
    
    Fraction Fraction::sub(const Fraction &other)
    {
        Fraction f1, f2, f3;
    
        f1.set(num, den);
        f2.set(other.num * -1, other.den);
    
        f3 = f1.add(f2);
        f3.set(f3.num * -1, f3.den);
        return f3;
    }
    
    Fraction Fraction::add(const Fraction &other)
    {
        Fraction fract;
        int lcd = lcm(den, other.den);
        int quot1 = lcd / den;
        int quot2 = lcd / other.den;
    
        fract.set(num * quot1 + other.num * quot2, lcd);
        return fract;
    }
    
    Fraction Fraction::mult(const Fraction &other)
    {
        Fraction fract;
    
        fract.set(num * other.num, den * other.den);
        return fract;
    }
    
    int Fraction::gcf(int a, int b)
    {
        if(a % b == 0)
        {
            return abs(b);
        }
        else
        {
            return gcf(b, a % b);
        }
    }
    
    int Fraction::lcm(int a, int b)
    {
        return (a / gcf(a, b)) * b;
    }
    
    void Fraction::normalize()
    {
        //handle cases involving 0
    
        if(den == 0 || num == 0)
        {
            num - 0;
            den = 1;
        }
    
        //put negative sign in numerator only
    
        if(den < 0)
        {
            num *= -1;
            den *= -1;
        }
    
        //factor out gcf from numerator and denominator
    
        int n = gcf(num, den);
        num /= n;
        den /= n;
    }
    FloatFraction class

    Code:
    #include <iostream>
    #include "Fract.h"
    using namespace std;
    
    class FloatFraction : public Fraction {
    public:
        FloatFraction() {set(0, 1);}
        FloatFraction(int n, int d) {set(n, d);}
        FloatFraction(int n) {set(n, 1);}
        FloatFraction(const FloatFraction &src)
            {set(src.get_num(), src.get_den());}
        FloatFraction(const Fraction &src)
            {set(src.get_num(), src.get_den());}
    
        double get_float() {
          return static_cast<double>(get_num())/get_den();}
    };
    
    int main() {
        FloatFraction f1(1, 2), f2(1, 3), f3;
    
        f3 = f1 + f2;
        cout << "Value of f3 is " << f3 << endl;
        cout << "Float value of f3 is " << f3.get_float() << endl;
    
    // TEST THE == OPERATOR
    
        if (f3 == FloatFraction(5, 6))
            cout << "1/2 + 1/3 is equal to 5/6." << endl;
        return 0;
    }
    I put the problem pieces of code in bold.

    The errors I am getting are:
    Floatfract1\main.cpp|103|error: passing 'const FloatFraction' as 'this' argument of 'int Fraction::get_num()' discards qualifiers|

    Like I said this is copied exactly from the book.

    I am not looking for an answer. I am just getting very frustrated. My understanding of these bolded lines of code is this:
    const means the value doesn't changes, the Fraction/FloatFraction is the type, and &src is a reference to some other object.
    Either a Fraction or a floatfraction, the code then should take this reference and use the items it has to set a new item.

    if its const FloatFraction &src it produces a FloatFraction, and if its const Fraction &src, it produces a Fraction.

    or is the purpose of
    Code:
    FloatFraction(const FloatFraction &src)
            {set(src.get_num(), src.get_den());}
    to provide a copy constructor, and the purpose of

    Code:
    FloatFraction(const Fraction &src)
            {set(src.get_num(), src.get_den());}
    to change the item to a Fraction?

    Maybe I don't exactly understand it correctly.

    The third subclass where I am running into problems is:
    Code:
    class ProperFraction : public FloatFraction
    {
        public:
            ProperFraction()
            {
                set(0, 1);
            }
            ProperFraction(int n)
            {
                set(n, 1);
            }
            ProperFraction(int n, int d)
            {
                set(n, d);
            }
            ProperFraction(const ProperFraction &src)
            {
                Fraction::set(src.Fraction::get_num, src.get_den);
            }
            ProperFraction(const FloatFraction &src)
            {
                set(src.Fraction::get_num, src.get_den);
            }
            ProperFraction(const Fraction &src)
            {
                set(src.Fraction::get_num, src.get_den);
            }
    
            void pr_proper(ostream &os);
            int get_whole();
            int get_num();  //overridden function
    };
    I once again put the problem lines in bold, if I leave the const I get this error message:
    Floatfract1\main.cpp|155|error: no matching function for call to 'ProperFraction::set(<unresolved overloaded function type>, <unresolved overloaded function type>)'|
    Floatfract1\fract.h|12|note: candidates are: void Fraction::set(int, int)|

    If I change the bolded lines to be
    Code:
    Fraction::set(src.Fraction::get_num, src.get_den);
    I receive the same error.

    If I remove the const it still produces the same error.


    Sorry about such a huge post, I was kind of hoping I'd figure it out as I went through whats going on but no luck. I am tempted to skip all this and move past getting the examples to work and just reading what the book says.
    Last edited by bob887; 12-31-2010 at 01:19 AM.

  2. #2
    -bleh-
    Join Date
    Aug 2010
    Location
    somewhere in this universe
    Posts
    463
    The problem is that both get_num() and get_den() are not const, so they could modify the "src" object. So when you use "const A & src", and then call on Fraction::get_num() and Fraction::get_den(), the compiler does not know the purposes of these two functions. But, since "src" cannot be modified, but these two function allows modification ( no const declaration), hence your compiler will throw a compiling error. To fixed that problem, just do:
    Code:
    int get_num() const {return num;}
    int get_den() const {return den;}
    By the way, i think it's better to use the constructor and copy constructor to initialize member variables than using the 'set' function.
    Last edited by nimitzhunter; 12-31-2010 at 02:27 AM.
    "All that we see or seem
    Is but a dream within a dream." - Poe

  3. #3
    Registered User
    Join Date
    Dec 2010
    Posts
    14
    Awesome thanks a lot for helping out, the Inheritance confuses me a little but I think I am starting to pick it up.

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    This isn't an inheritance issue, though. This is a basic const issue. A const function may not call a non-const function (the guarantee of const would be lost since the non-const function could modify the object).
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Inheritance and program structure planning please help a newbie
    By ninjacookies in forum C++ Programming
    Replies: 1
    Last Post: 10-23-2005, 12:18 PM
  2. inheritance problems
    By generic83 in forum C++ Programming
    Replies: 5
    Last Post: 04-10-2005, 05:04 PM
  3. Multiple Inheritance - Size of Classes?
    By Zeusbwr in forum C++ Programming
    Replies: 10
    Last Post: 11-26-2004, 09:04 AM
  4. Inheritance problems
    By alkis_y3k in forum C++ Programming
    Replies: 5
    Last Post: 01-03-2003, 06:00 PM
  5. DJGPP problems
    By stormswift in forum C Programming
    Replies: 2
    Last Post: 02-26-2002, 04:35 PM