views:

100

answers:

5

I am making a fraction class for a school project, and my brain is frying. I was told to overload the << and >> operators through the friend keyword. But I'm getting errors for this.

I've posted the relevant code here: http://pastebin.com/NgCABGJ2

The errors include: error C2270: '<<' : modifiers not allowed on nonmember functions (this error is for all the ones that are declared as friends)

This was at the operator< definition. error C2333: 'Fraction::operator <' : error in function declaration; skipping function body

There's 46 in all... this is a nightmare.

EDIT:

Thanks, I solved almost all the errors, but there's still 3

error C2664: 'Fraction::Fraction(const Fraction &)' : cannot convert parameter 1 from 'int' to 'const Fraction &' Occurs at this statement:

Fraction<int> test1, test2, test3(10);

error C2248: 'Fraction::operator ==' : cannot access private member declared in class 'Fraction' error C2248: 'Fraction::operator <' : cannot access private member declared in class 'Fraction'

I don't understand these two, but it occurs at these statements:

    if (test1 == test2)
    cout << "\nTest1 is equal to Test2";
if (test1 < test2)
    cout << "\nTest1 is less than Test2";

Thanks!

<><><>>EDIT2<<><><>

I fixed the other private access errors, but now i have some reaaaaaaaally bizarre errors:

Full code: http://pastebin.com/MVrB67SR

Errors:

Error 1 error LNK2001: unresolved external symbol "class Fraction __cdecl operator-(class Fraction const &,class Fraction const &)" (??G@YA?AV?$Fraction@H@@ABV0@0@Z) Error 2 error LNK2001: unresolved external symbol "class Fraction __cdecl operator+(class Fraction const &,class Fraction const &)" (??H@YA?AV?$Fraction@H@@ABV0@0@Z) Error 3 error LNK2001: unresolved external symbol "class Fraction __cdecl operator/(class Fraction const &,class Fraction const &)" (??K@YA?AV?$Fraction@H@@ABV0@0@Z) c:\Users\caleb jares\documents\visual studio 2010\Projects\Solution11-5\Solution11-5\Solution11-5.obj Error 4 error LNK2001: unresolved external symbol "class Fraction __cdecl operator*(class Fraction const &,class Fraction const &)" (??D@YA?AV?$Fraction@H@@ABV0@0@Z) Error 5 error LNK2001: unresolved external symbol "class std::basic_ostream > & __cdecl operator<<(class std::basic_ostream > const &,class Fraction)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@ABV01@V?$Fraction@H@@@Z) Error 6 error LNK2001: unresolved external symbol "class std::basic_istream > & __cdecl operator>>(class std::basic_istream > const &,class Fraction)" (??5@YAAAV?$basic_istream@DU?$char_traits@D@std@@@std@@ABV01@V?$Fraction@H@@@Z) Error 7 error LNK1120: 6 unresolved externals

Again, thanks for help!

A: 

The const keyword following the function declaration is only allowed for member functions:

// This is not a member function!
template <class T>
ostream& operator<<(const ostream& output,
                    const Fraction<T>& value) /* No const! */
{
    // ...
}

It's not allowed because a const at the end of a member function declaration means this member function will not modify non-mutable values of the *this object. Since this is a non-member function, a const applied to the end of the function declaration is an error.

Also, if you define the < operator (or other operators like >, +, -, etc.) as a member of the class, it can only accept a single parameter:

// Only accepts a single parameter (the "right-hand-side" argument)
bool operator<(Fraction<T> const& right) const
{
    // ...
}

Although as Potatoswatter has pointed out, you should define these kinds of operators outside the class as free functions.

In silico
Member `operator` definitions can end up with surprising interactions with polymorphism and function call semantics. As a habit, free functions are better.
Potatoswatter
+1  A: 

Just take the const off... they're not member functions, so they can't be const. You should pass the class object by reference too... no point making copies all the time.

Tony
thanks for the answer. maybe you can explain why they can't be const?
cable729
@cable729: If a member function is declared `const` it means that it doesn't modify the object it is called on (the object `this` points to inside the function). For a non-member function there is no such object (there is no `this`), so there is nothing that could be const.
sth
Thanks! makes perfect sense!
cable729
+1  A: 

Sounds like you tried to declare friend ostream &operator<<(…) const; . The important thing about friends is that they are not members. A friend function exists outside the scope of the class, even if it is defined inside the class {} block. In other words, you are declaring a function ::operator<<(), not fraction::operator<<(). And only member functions can have that trailing const, since it modifies the type of this.

Fact is, operator<< for output usually shouldn't be a friend anyway. It just gets the value and forwards it to the stream… that shouldn't require any special permission! Same applies to operator<.

Take the functions outside the class block entirely. There's no way your TA can complain about your design using friend less often.

Potatoswatter
Thanks! this makes so much sense! And, you're saying I should define operators outside the body? I didn't know that was possible. Do I have to make a declaration (ie. bool thisfunction();) and define (implement it - bool thisfunction() {...}) it outside? Sorry I don't know the vocabulary for that.
cable729
@cable: Yep, entirely correct. Like I said, defining a `friend` function inside `class{}` is the same as defining it outside `class{}`, so you're already almost there. Just copy-paste. Oh, there is one difference — you have to qualify names of static members and nested types. But you don't have any of those, as you shouldn't :v) .
Potatoswatter
A: 

The modifiers it's referring is the const at the end of the function, after the parameters:

friend ostream& operator<<(const ostream& output, const Fraction<T> value) const; //<-- that
friend istream& operator>>(const istream& input, Fraction<T> value) const; // <-- and that

The const modifier indicates that the function doesn't modify the object that it belongs to. Since they aren't member functions, they don't belong to any object.

PigBen
+1  A: 

I can't figure out the first of your new errors, but the operator== and operator< errors are because they're private inside your class by default. You need a public: line in front of them so they're accessible to the outside world.

Mark B