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:
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 << "The result starts off at ";
result.print();
cout << endl;
cout << "The product of ";
f1.print();
cout << " and ";
f2.print();
cout << " is ";
result = f1.MultipliedBy(f2);
result.print();
cout << endl;
cout << "The quotient of ";
f1.print();
cout << " and ";
f2.print();
cout << " is ";
result = f1.DividedBy(f2);
result.print();
cout << endl;
cout << "The sum of ";
f1.print();
cout << " and ";
f2.print();
cout << " is ";
result = f1.AddedTo(f2);
result.print();
cout << endl;
cout << "The difference of ";
f1.print();
cout << " and ";
f2.print();
cout << " is ";
result = f1.Subtract(f2);
result.print();
cout << endl;
if (f1.isEqualTo(f2)){
cout << "The two fractions are equal." << endl;
} else {
cout << "The two fractions are not equal." << endl;
}
const fraction f3(12, 8);
const fraction f4(202, 303);
result = f3.MultipliedBy(f4);
cout << "The product of ";
f3.print();
cout << " and ";
f4.print();
cout << " is ";
result.print();
cout << endl;
system("PAUSE");
}
Here's my fraction.h file:
ifndef FRACTION_H
define FRACTION_H
class fraction
{
public:
fraction();
fraction(int initNumerator, int initDenominator);
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 << "The product of ";
f3.print();
cout << " and ";
f4.print();
cout << " is ";
result.print();
cout << endl;
system("PAUSE");
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
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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:
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:
(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
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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: passing
const fraction' asthis' argument of
fraction fraction::MultipliedBy(fraction)' discards qualifiersmake.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;
}
Here's my fraction.h file:
ifndef FRACTION_H
define FRACTION_H
class fraction
{
public:
fraction();
fraction(int initNumerator, int initDenominator);
};
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;
}
fraction fraction::DividedBy(fraction divider)
{
fraction answer;
}
fraction fraction::AddedTo(fraction added)
{
fraction answer;
}
fraction fraction::Subtract(fraction subtracted)
{
fraction 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():
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
Thanks for the help Clifford and Ron. I got it figured out. The explanation really helped.
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);
Oops, wrong line.
reduce(); // problem is here
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