Menu

using const in conjuction with classes

Ted
2008-11-12
2012-09-26
  • Ted

    Ted - 2008-11-12

    Hi,

    I'm taking a C++ basics class and I need some help. This assignment is an intro to working with classes, and I have to build a class that displays fractions in the form 'someInt/someInt'. I have been given the code for main(), but I am not allowed to modify it in any way, and have to build a class that makes it work. I get the following error message when compiling:

    Compiler: Default compiler
    Building Makefile: "F:\CIS10\Project3\Attempt2\Makefile.win"
    Executing make...
    make.exe -f "F:\CIS10\Project3\Attempt2\Makefile.win" all
    g++.exe -c main.cpp -o main.o -I"C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include" -I"C:/Dev-Cpp/include/c++/3.4.2/backward" -I"C:/Dev-Cpp/include/c++/3.4.2/mingw32" -I"C:/Dev-Cpp/include/c++/3.4.2" -I"C:/Dev-Cpp/include"

    main.cpp: In function int main()': main.cpp:61: error: passingconst fraction' as this' argument offraction fraction::MultipliedBy(fraction)' discards qualifiers

    make.exe: *** [main.o] Error 1

    Execution terminated

    Here is the code for main(). Again I cannot modify this in any way:

    include <cstdlib>

    include <iostream>

    include "fraction.h"

    using namespace std;

    int main()
    {
    fraction f1(9,8);
    fraction f2(2,3);
    fraction result;

    cout &lt;&lt; &quot;The result starts off at &quot;;
    result.print();
    cout &lt;&lt; endl;
    
    cout &lt;&lt; &quot;The product of &quot;;
    f1.print();
    cout &lt;&lt; &quot; and &quot;;
    f2.print();
    cout &lt;&lt; &quot; is &quot;;
    result = f1.MultipliedBy(f2);
    result.print();
    cout &lt;&lt; endl;
    
    cout &lt;&lt; &quot;The quotient of &quot;;
    f1.print();
    cout &lt;&lt; &quot; and &quot;;
    f2.print();
    cout &lt;&lt; &quot; is &quot;;
    result = f1.DividedBy(f2);
    result.print();
    cout &lt;&lt; endl;
    
    cout &lt;&lt; &quot;The sum of &quot;;
    f1.print();
    cout &lt;&lt; &quot; and &quot;;
    f2.print();
    cout &lt;&lt; &quot; is &quot;;
    result = f1.AddedTo(f2);
    result.print();
    cout &lt;&lt; endl;
    
    cout &lt;&lt; &quot;The difference of &quot;;
    f1.print();
    cout &lt;&lt; &quot; and &quot;;
    f2.print();
    cout &lt;&lt; &quot; is &quot;;
    result = f1.Subtract(f2);
    result.print();
    cout &lt;&lt; endl;
    
    if (f1.isEqualTo(f2)){
        cout &lt;&lt; &quot;The two fractions are equal.&quot; &lt;&lt; endl;
    } else {
        cout &lt;&lt; &quot;The two fractions are not equal.&quot; &lt;&lt; endl;
    }
    
    const fraction f3(12, 8);
    const fraction f4(202, 303);
    result = f3.MultipliedBy(f4);
    cout &lt;&lt; &quot;The product of &quot;;
    f3.print();
    cout &lt;&lt; &quot; and &quot;;
    f4.print();
    cout &lt;&lt; &quot; is &quot;;
    result.print();
    cout &lt;&lt; endl;
    
    system(&quot;PAUSE&quot;);
    

    }


    Here's my fraction.h file:

    ifndef FRACTION_H

    define FRACTION_H

    class fraction
    {
    public:
    fraction();
    fraction(int initNumerator, int initDenominator);

        ~fraction();
    
        void print() const;
        void fraction::set(int, int);  
        fraction fraction::MultipliedBy(fraction);
        fraction fraction::DividedBy(fraction);
        fraction fraction::AddedTo(fraction);
        fraction fraction::Subtract(fraction);
        bool fraction::isEqualTo(fraction);
        void fraction::reduce();
    
    private: 
        int numer; 
        int denom;
    

    };

    endif


    And here's my fraction.cpp file (no documentation yet):

    include <iostream>

    include "fraction.h" // class's header file

    using namespace std;

    /*************

    *************/

    fraction::fraction()
    {
    numer = 0;
    denom = 1;
    }

    fraction::~fraction()
    {
    }

    fraction::fraction(int initNumerator,
    int initDenominator)
    {
    numer = initNumerator;
    denom = initDenominator;
    }

    void fraction::print() const
    {
    cout << numer << "/" << denom;
    }

    void fraction::set(int inNumer,
    int inDenom)
    {
    numer = inNumer;
    denom = inDenom;
    }

    fraction fraction::MultipliedBy(fraction multiplier)
    {
    fraction answer;

     reduce();
     multiplier.reduce();
     answer.set (numer * multiplier.numer, denom * multiplier.denom);
     answer.reduce();
    
     return answer;
    

    }

    fraction fraction::DividedBy(fraction divider)
    {
    fraction answer;

     reduce();
     divider.reduce();
     answer.set(numer * divider.denom, denom * divider.numer);
     answer.reduce();
    
     return answer;
    

    }

    fraction fraction::AddedTo(fraction added)
    {
    fraction answer;

     reduce();
     added.reduce();
     answer.set((numer * added.denom) + (denom * added.numer), denom * added.denom);
     answer.reduce();
    
     return answer;
    

    }

    fraction fraction::Subtract(fraction subtracted)
    {
    fraction answer;

     reduce();
     subtracted.reduce();
     answer.set((numer * subtracted.denom) - (denom * subtracted.numer), denom * subtracted.denom);
     answer.reduce();
    
     return answer;
    

    }

    bool fraction::isEqualTo(fraction compare)
    {
    return (numer == compare.numer && denom == compare.denom);
    }

    void fraction::reduce()
    {
    while (numer % 2 == 0 && denom % 2 == 0){
    set(numer / 2, denom / 2);
    }
    while (numer % 3 == 0 && denom % 3 == 0){
    set(numer / 3, denom / 3);
    }
    if (numer == denom)
    set(1,1);
    }


    When I take the const tags out of this section of main():

    const fraction f3(12, 8);
    const fraction f4(202, 303);
    result = f3.MultipliedBy(f4);
    cout &lt;&lt; &quot;The product of &quot;;
    f3.print();
    cout &lt;&lt; &quot; and &quot;;
    f4.print();
    cout &lt;&lt; &quot; is &quot;;
    result.print();
    cout &lt;&lt; endl;
    
    system(&quot;PAUSE&quot;);
    

    the program works perfectly. When I add it back the program breaks. And the assignment specifically states taht I cannot modify main(). What do I do to fix this? I'm sure it's really basic but I'm totally new to this. Thanks in advance for any help. This is a great resource.

    Ted

     
    • Ted

      Ted - 2008-11-12

      Thanks for the help Clifford and Ron. I got it figured out. The explanation really helped.

       
    • Ron McHugh

      Ron McHugh - 2008-11-12

      You are trying to modify a constant object.

      fraction fraction::MultipliedBy(fraction multiplier)
      {
      fraction answer;
      reduce();
      multiplier.reduce(); // problem is here
      answer.set (numer * multiplier.numer, denom * multiplier.denom);
      answer.reduce();
      return answer;
      }

      To fix this you need to just copy the multiplier into a non-const object so you then can modify its values.

      To better the design of your class you should make the functions parameter constant like...

      fraction::MultipliedBy(const fraction multiplier);

       
    • Ron McHugh

      Ron McHugh - 2008-11-12

      Oops, wrong line.

      reduce(); // problem is here

       
    • cpns

      cpns - 2008-11-12

      I wrote the following and then realised I was repeating some of what Ron had said. However, Ron has pointed out only that the parameter is const, but the object itself is const also (both f3 and f4), so I'll let my explanation stand since it still adds value:

      The main function requires that f3 and f4 are not modified by calling f3.MultipliedBy( f4 ). This is not unreasonable since it returns a result object. If it did modify the arguments that would be the same as when you evaluate a = b * c, expecting b and c to change value!

      The problem is that ultimately in the set() function attempts to modify the internal representation of teh arguments. You cannot reduce the arguments therefore, only the result.

      For complete const correctness, you should declare the function thus:

      fraction fraction::MultipliedBy(const fraction) const ;

      which says "I don't modify myself, and I don't modify the argument". Of course you will then have to implement the function so it complies with those guarantees - which means not trying to reduce the arguments.

      The simple solution is in MultipliedBy() to create:

      fraction a = *this ;
      fraction b = multiplier ;

      a and b are temporary and not const and can be reduced. You don't touch the arguments.

      Further for complete const-safety other member functions should be changed too:

      fraction fraction::MultipliedBy(const fraction) const ;
      fraction fraction::DividedBy(const fraction) const ;
      fraction fraction::AddedTo(const fraction) const ;
      fraction fraction::Subtract(const fraction) const ;
      bool fraction::isEqualTo(const fraction) const ;

      (obviously you change teh definitions as well as the declarations to match).

      If you do that and it fails to compile, you are modifying an argument when you should not. Such attention to detail may get you a few extra marks. Of course you may also be queried on it so make sure you understand why it is so! I am assuming that your tutor made them const exactly to allow you to demonstarte your understanding of const.

      Clifford

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.