C++ typecasting vs implicit constructor - c++

I'm implementing a c++-class representing a fraction. Here goes my code.
class Fraction
{
public:
Fraction(char i);
Fraction(int i);
Fraction(short i);
Fraction(long int l);
#ifdef __LP64__
Fraction(long long l);
#endif
Fraction(float f);
Fraction(double d);
Fraction(double x, double y);
Fraction operator +() const;
Fraction operator -() const;
Fraction& operator +=(const Fraction& other);
Fraction& operator -=(const Fraction& other);
Fraction& operator *=(const Fraction& other);
Fraction& operator /=(const Fraction& other);
bool operator ==(const Fraction& other);
bool operator !=(const Fraction& other);
bool operator >(const Fraction& other);
bool operator <(const Fraction& other);
bool operator >=(const Fraction& other);
bool operator <=(const Fraction& other);
operator double();
operator float();
static void commonize(Fraction& a, Fraction& b);
void shorten();
double getNumerator();
double getDenominator();
friend Fraction operator +(Fraction const& a, Fraction const& b);
friend Fraction operator -(Fraction const& a, Fraction const& b);
friend Fraction operator *(Fraction const& a, Fraction const& b);
friend Fraction operator /(Fraction const& a, Fraction const& b);
friend ostream& operator <<( ostream& o, const Fraction f);
protected:
double numerator, denominator;
};
I now have two little problems.
Now trying to call
Fraction a(1, 2);
cout << (3 + a) << endl;
simply results in this error:
fractiontest.cpp:26: error: ambiguous overload for ‘operator+’ in ‘3 + a’
fractiontest.cpp:26: note: candidates are: operator+(int, double) <built-in>
fractiontest.cpp:26: note: operator+(int, float) <built-in>
All I'd really want is this:
explicit operator double();
explicit operator float();
But apparently, this doesn't work. I'd like these two cast-operators to be called iff I use the cast notation. For example Fraction f(1, 2); double d = (double)(f);

By definition the conversion operators are implicit. You can't make them explicit.
The normal solution is named member functions to do the conversion. I think you could also create a specialized template method that would look just like a static_cast and call through to the explicit class method.

Remove the conversion operators and 3 + a should use your friend operator+ while implicitly converting 3 to Fraction via the implicit constructor Fraction(int i);.
Edit: On the case of the explicit conversion operators, C++0x specifically allows this:
12.3.2 [class.conv.fct] p2
A conversion function may be explicit, in which case it is only considered as a user-defined conversion for direct-initialization.
The C++03 standard doesn't specifically mention this.

Related

Returning a vector containing objects by reference

I am trying to write a function that returns a vector consisting of n random Fractions. I am getting a strange error telling me to "see reference to function template instantiation, and that "class Fraction: no copy constructor available or copy constructor is declared 'explicit'". Any help is greatly appreciated.
Here is the code I have written:
vector<Fraction> & genV(int n) {
vector<Fraction> temp;
for (int i = 0; i < n; i++) {
int n, d;
n = rand() % (100);
d = rand() % (100);
// create a new random fraction
Fraction *tempFraction = new Fraction(n, d);
// push new fraction to vector
temp.push_back(*tempFraction);
}
return temp;
}
Here is the header file:
#ifndef FRACTION_H
#define FRACTION_H
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
class Fraction {
private:
int *numerator;
int *denominator;
public:
int getNumerator();
int getDenominator();
void reduce();
int gcd(int, int);
// constructors
Fraction(); // default c'tor
Fraction(int n); // create a fraction of n/1
Fraction(int n, int m); // Fraction n/m
Fraction(Fraction & other); // copy c'tor
~Fraction(); // destructor
Fraction & operator=(Fraction & rhs);
// overload assignment operator
Fraction & operator+(Fraction &rhs);
Fraction & operator-(Fraction &rhs); // overload binary operator -
Fraction & operator-(); // overload unary operator - (negative)
Fraction & operator *(Fraction &rhs);
Fraction & operator/(Fraction & rhs);
Fraction & operator++();// overload prefix ++
Fraction & operator++(int); // overload postfix ++
Fraction & operator--();// overload prefix --
Fraction & operator--(int); // overload postfix --
// overload relational operators
bool operator >(Fraction & rhs); // return true if *this > rhs , false elsewise
bool operator == (Fraction & rhs);
bool operator < (Fraction & rhs);
bool operator !=(Fraction &rhs);
Fraction & operator+=(Fraction & rhs);
Fraction & operator-=(Fraction & rhs);
Fraction & operator*=(Fraction & rhs);
Fraction & operator/=(Fraction & rhs);
string toString();
char * toCstring();
bool isZero(); // return true if *this is zero
int power(int base, int exp);
Fraction & operator^(int n);
friend istream & operator >> (istream & in, Fraction & rhs);
friend ostream & operator << (ostream & out, Fraction & rhs);
};
#endif
this Fraction(Fraction & other); // copy c'tor isn't a copy constructor.
this Fraction(const Fraction & other); // copy c'tor is a copy constructor.
And the reason why you aren't getting the default one is because you disabled the automatic generation of it with the other declarations.

c++ simple operator overloading for both directions

So I am trying to overload the operator* so both ways will work:
Myclass * a;
a * Myclass;
When I declare this function everything goes well:
Polynomial operator*(const double d);
But when I try doing it the other direction like this:
Polynomial operator*(Polynomial &, const double d)
I'm getting an error: "too many parameters for this operator function.
What am I doing wrong?
Thanks!
When you overload a binary operator as a member function, the class instance is always the left-hand operator and the argument to the function is the right hand, there's nothing you can do to change it. Not if you want to continue using member only functions.
But if you use a global non-member function you can easily have whichever order you want. For example
class Polynomial { ... };
// Function that allows poly * 12.34
Polynomial operator*(const Polynomial& lhs, const double rhs)
{
...
}
// Function which allows 12.34 * poly
Polynomial operator*(const double lhs, const Polynomial& rhs)
{
...
}
And if you don't want to reimplement the same code in both functions, and the operator is commutative (like multiplication and addition should be) then you can implement one of the function by calling the other:
Polynomial operator*(const Polynomial& lhs, const double rhs)
{
...
}
Polynomial operator*(const double lhs, const Polynomial& rhs)
{
return rhs * lhs; // Calls the operator function above
}
Of course, the operator taking the Polynomial object as left-hand side may of course be implemented as a member function.
On a related note, if you have implemented the operator as a member function, e.g.
class Polynomial
{
...
Polynomial operator*(const double rhs)
{
...
}
};
The the following code
Polynomial poly1(...);
Polynomial poly2 = poly * 12.34;
is equal to
Polynomial poly1(...);
Polynomial poly2 = poly.operator*(12.34);

implicit assignment operators

If I have an operator overload on my class, is the assignment version of the operator implicitly created as well?
class square{
square operator+(const square& B);
void operator=(const square& B);
};
As in, can I then call
square A, B;
A += B;
with the compiler implicitly deciding to call operator+ then operator=?
No, += must be defined explicitly.
As a side note, operator+ should usually create a new object:
square operator+(const square& B);
And operator= should return a reference to *this:
square& operator=(const square& B);
Also worth noting that operator+ is usually implemented in terms of operator+=, i.e. operator+ calls operator+= on the new copy.
No, the operators aren't implicitly defined. However, boost/operators.hpp defines useful helper templates to avoid boiler-plate code. Example from their docs :
If, for example, you declare a class like this:
class MyInt
: boost::operators<MyInt> {
bool operator<(const MyInt& x) const;
bool operator==(const MyInt& x) const;
MyInt& operator+=(const MyInt& x);
MyInt& operator-=(const MyInt& x);
MyInt& operator*=(const MyInt& x);
MyInt& operator/=(const MyInt& x);
MyInt& operator%=(const MyInt& x);
MyInt& operator|=(const MyInt& x);
MyInt& operator&=(const MyInt& x);
MyInt& operator^=(const MyInt& x);
MyInt& operator++();
MyInt& operator--(); };
then the operators<> template adds more than a dozen additional operators, such as operator>, <=, >=, and
(binary) +. Two-argument forms of the templates are also provided to
allow interaction with other types.
In addition, there is also support for implicitly "deducing" just a specific set of operators using arithmetic operator templates.
No operator+= is its own operator and must be defined explicitly.
Note that operator+ should return a new object rather than a reference to the original object. The original object should be left unchanged.
operator+= should return the original object with the required value added. operator+= is often preferable as it eliminates a temporary object.

C++ error with operator overloading

I am trying to make program that uses operator overloading to do basic math operations on rational numbers. I keep getting an errors in the functions where it says i must have an arithmetic of enum type. Also I get an error istream where it says that the numerator and denominator are undefined.
Here is the header file:
#ifndef rational_H
#define rational_H
#include <iostream>
using namespace std;
class Rational
{
friend ostream & operator<<(ostream & , const Rational &);
friend istream & operator<<(istream & , const Rational &);
public:
// default constructor
Rational(int = 0, int = 1);
// overload operators for "normal" operation
Rational operator+(const Rational&);
Rational operator-(const Rational&);
Rational operator*(const Rational&);
Rational operator/(const Rational&);
operator double();
// overload relational operators for "normal" operation
bool operator>(const Rational&) const;
bool operator<(const Rational&) const;
bool operator>=(const Rational&) const;
bool operator<=(const Rational&) const;
bool operator==(const Rational&) const;
bool operator!=(const Rational&) const;
protected:
int *numerator;
int *denominator;
void reduction(void);
};
#endif
// this part of code is from my rational cpp file//
// default constructor//
Rational::Rational( int n, int d )
{
*numerator =1 ;
// sets numerator
if(d == 0)
d = 1; // If denominator is zero then set to one.
*denominator = 0;
// sets denominator
reduction(); // store the fraction in reduced form
}
// all the other operators have the same error as well//
Rational Rational::operator-(const Rational&a)
{
Rational sub;
sub.numerator = *this->numerator * a.denominator -//the error is with the 'a'needs to be an arithmetic type or enum type//
*this->denominator * a.numerator;
sub.denominator = *denominator * a.denominator;
sub.reduction();
return sub;
}
//also the istream part has an error where the denominator and numerator is underfined as well//
istream& operator >> ( istream& inputStream, Rational& rnum )
{
inputStream>>rnum.*numerator;//numerator and denmoinator undefined for some reason//
inputStream.ignore(1);
inputStream>>rnum.*denominator;
return inputStream;
}
There are multiples small errors in your code.
First of all you should not be using pointers for these members, it does not bring any advantages.
But as you chose this way, you have to dereference them each time you want to read or update them, which hasn't be done in your operator- implementation, and incorrectly in your operator>> implementation (the asterisk needs to be put before the whole expression).
Next error in the code you provided, you marked as friend operator<<(istream & , const Rational &) in your class definition, but it should have been operator>>. And this declaration needs to match the definition that appears next (i.e., remove the const of the second argument, which obviously has to be mutated).
And, last but not least, the undefined behavior caused by all the dereferencing of you uninitialized pointers…
This is probably a copy and past error. The line
friend istream & operator<<(istream & , const Rational &);
should be
friend istream & operator>>(istream & , Rational &);
Your implementation later on in the file has:
istream& operator >> ( istream& inputStream, Rational& rnum )
{
...
}
It matches the second declaration, not the first one.

Operator Overloading in C++ (small error)

I have a small error with operator overloading that's been bugging me.
I've got a class:
class Fraction{
private:
//Variables
int numerator;
int denominator;
//Constructor
public:
//Methods
Fraction();
Fraction(int, int);
};
I also have this operator overloading function:
Fraction& operator+=(const Fraction& f);
It seems like it would build fine to me, but the compiler is giving me this error message:
In file included from Fraction.cpp:3:
./Fraction.h:31:11: error: overloaded 'operator+=' must be a binary operator
(has 1 parameter)
Fraction& operator+=(const Fraction& f);
^
1 error generated.
Every single example of += I've seen so far is identical to what I'm doing as far, from what I can tell. If someone could point out my stupidity, that would be great!
Either declare the operator as a member function of the class or if it is a non-class function then it shall have two parameters
For example
1 member function
class Fraction
{
private:
//Variables
int numerator;
int denominator;
//Constructor
public:
//Methods
Fraction();
Fraction(int, int);
Fraction& operator +=( const Fraction &rhs );
};
2. non-member function
class Fraction
{
private:
//Variables
int numerator;
int denominator;
//Constructor
public:
//Methods
Fraction();
Fraction(int, int);
friend Fraction& operator +=( Fraction &lhs, const Fraction &rhs );
};
Fraction& operator +=( Fraction &lhs, const Fraction &rhs ) { /* some code */ }
Take into account that then the operator is a non-class function you may not use this
Also the non-class operator should be a friend function of the class if there is no public access to corresponding data members through getters and setters.
You should put
Fraction& operator+=(const Fraction& f);
declaration inside class if it has to be binary operation. Alternatively you can declare this operator in global namespace taking two instances of Fraction, but make it friend of this class (as it needs access to private data) by declaring friendship in Fraction through:
friend Fraction& operator+=( Fraction& l, const Fraction& r);
You are defining a free function, it should have 2 parameters (binary operator).
Declare it inside the Fraction class instead.
If you overload the operator as a non-member function you need to write it like this
Fraction& operator+=(const Fraction& lhs, const Fraction& rhs);
This errors occurs when your overloaded operator is outside your class as global.
You should try give declaration of this operator into your class as:
Fraction& operator+=(const Fraction& f);
You can leave as you did but then you must change operator to this:
Fraction& operator+=(const Fraction& f, const Fraction& g);
Here you can find some more information in my post