hi, i read in ebook about overleaded iostream operator for class, but im a bit confused about this one :

ostream &operator << (ostream &strm, const FeetInches &obj)
{
   strm << obj.feet << " feet, " << obj.inches << " inches";
   return strm;
}

Notice the function has two parameters: an ostream reference object and a const
FeetInches reference object. The ostream parameter will be a reference to the actual ostream object on the left side of the << operator. The second parameter is a reference to a FeetInches object. This parameter will reference the object on the right side of the << operator. This function tells C++ how to handle any expression that has the following form:
ostreamObject << FeetInchesObject

So, when C++ encounters the following statement, it will call the overloaded operator << function:
cout << distance;

Notice that the function's return type is ostream &. This means that the function returns a reference to an ostream object. When the return strm; statement executes, it doesn't return a copy of strm, but a reference to it. This allows you to chain together several expressions using the overloaded << operator, such as:
cout << distance1 << " " << distance2 << endl;

my question is : the statement that says

**the function returns a reference to an ostream object, when the "return strm" statement executes it doesn't return a copy of strm, but a reference to it, this allows yout to chain together several expressions using the overloaded << operator. **

so whats the problem when it returns a copy of strm? i dont get it , my head is confused because of the parameter already a reference of an ostream object, and the function then need to return a reference ostream object in order to chain several expression using << operator.... anyone can explain?

ermm and 1 more problem... after i read it, i tried to make a simple program that uses and test the overloaded operator, and it has problems..

here's the main.cpp:

#include "FeetInches.h"
#include <iostream>

using namespace std;

int main()
{
    //define FeetInches object and passing arguments to constructor
    FeetInches one(6, 32);  
    FeetInches two(5, 4);
    /*using overloaded operator "+" to add FeetInches object named "one" and "two" and store the value to "three" */
    FeetInches three = one + two;
    cout<<"one + two = "<<three.getFeet()<<" "<<three.getInches()<<endl;
    cout<<one<<endl<<two<<endl<<three;
}

here's the FeetInches class declaration :

#ifndef FEETINCHES_H
#define FEETINCHES_H
#include <iostream>
#include <cstdlib>

using namespace std;

class FeetInches;

class FeetInches
{
    private:
    int feet;
    int inches;

    public:
    FeetInches(int f = 0, int i = 0)
    {
        feet = f;
        inches = i;
    }
    int getInches() const
    {
        return inches;
    }
    int getFeet() const
    {
        return feet;
    }

    void simplify();

    FeetInches operator=(const FeetInches&);
    FeetInches operator+(const FeetInches&);
    FeetInches operator-(const FeetInches&);
    FeetInches operator++();
    FeetInches operator++(int);
    bool operator>(const FeetInches&);
    bool operator<(const FeetInches&);

    friend ostream& operator<<(ostream & , const FeetInches &);
    friend istream& operator>>(istream & ,  FeetInches &);

};

#endif

FeetInches implementation file:

#include "FeetInches.h"
#include <iostream>
#include <cstdlib>

using namespace std;

void FeetInches::simplify()
{
        if(inches > 0)
        {
            feet = feet + (inches / 12);
            inches = inches % 12;
        }
        else if(inches < 0)
        {
            feet = feet - ((abs(inches) / 12) +1);
            inches = 12 - (abs(inches) % 12);

        }
}



FeetInches FeetInches::operator=(const FeetInches& right)
{
    feet = right.feet;
    inches = right.inches;
    return *this;
}

FeetInches FeetInches::operator+(const FeetInches& right)
{
    FeetInches temp;
    temp.feet = feet + right.feet;
    temp.inches = inches + right.inches;
    temp.simplify();
    return temp;
}

FeetInches FeetInches::operator-(const FeetInches& right)
{
    FeetInches temp;
    temp.feet = feet - right.feet;
    temp.inches = inches - right.inches;
    temp.simplify();
    return temp;
}

FeetInches FeetInches::operator++()
{
    inches++;
    simplify();
    return *this;
}

FeetInches FeetInches::operator++(int)
{
    FeetInches temp(feet, inches);
    inches++;
    simplify();
    return temp;
}

bool FeetInches::operator>(const FeetInches& right)
{
    bool status;
    if(feet > right.feet)
    {
        status = true;
    }
    else if(feet == right.feet && inches > right.inches)
    {
        status = true;
    }
    else
    {
        status  = false;
    }

    return status;
}

bool FeetInches::operator<(const FeetInches& right)
{
    bool status;

    if(feet < right.feet)
    {
        status = true;
    }
    else if(feet == right.feet && inches < right.inches)
    {
        status = true;
    }
    else
    {
        status = false;
    }

    return status;
}



ostream& FeetInches::operator<<(ostream& strm, const FeetInches right&)
{
    strm<<rigth.feet<<" feet"<<right.inches<<" inches";
    return strm;
}

istream& FeetInches::operator>>(istream& strm, FeetInches right&)
{
    cout<<"enter feet ";
    strm>>right.feet;
    cout<<"enter inches ";
    strm>>right.inches;
    right.simplify();
    return strm;
}

i have problems with it, it has some errors T_T.. anyone can help me?

im really sorry for this long post, and alot of question.. its because im learning on my own and i cant ask anyone except here, i already tried to use search engine for further explanation, but i still dont get clear answer..

note: sorry for the bad english

Recommended Answers

All 9 Replies

Could you tell us what the errors you are getting are, as well as which compiler and platform you are using?

One thing I will recommend right off the bat is to remove the using namespace std; from both the header and the implementation file for your class, and explicitly scope the stream objects. As is explained here, this can cause a problem when using a friend function, in that the type declarations (which appear to refer to the std:: namespace) are actually referring to the global namespace - where no such type declarations exist.

std::ostream& FeetInches::operator<<(std::ostream& strm, const FeetInches right&)
{
    strm << right.feet << " feet, " << right.inches << " inches";
    return strm;
}

Second, I would stringly recommend against explicitly polling the user for the input the way you have it now. The reason for this is because you don't know for certain which I/O stream you'll be getting the input from; if you apply the operator to a file stream, for example, it may cause the input to fail.

In your assignment operator, you should be checking for self assignment. In your addition/subtraction operators, I'm not sure that you need that temp there. Your ostream works right out of the box. The reason you're getting these errors is because the files aren't added to your debug and release upon compilation.

If using codeblocks, right click the header and implementation files and press remove. Right click the project and add files. Hold control and click both files to add both of them. Check off Debug AND Release. Compile and it works.

I've made the changes to your assignment operator and the addition/subtraction. I don't think there is a problem returning a copy of the object to the stream but there will be a problem returning a copy of the stream to itself.. So a reference is returned. At least that's the way I see it.

Header:

#ifndef FEETINCHES_H_INCLUDED
#define FEETINCHES_H_INCLUDED

#include <iostream>
#include <cstdlib>

using namespace std;

class FeetInches
{
    private:
        int Feet;
        int Inches;

    public:
        FeetInches(int F = 0, int I = 0);
        int GetInches() const;
        int GetFeet() const;
        void Simplify();
        const FeetInches& operator = (const FeetInches& FI);
        FeetInches& operator + (const FeetInches& FI);
        FeetInches& operator - (const FeetInches& FI);
        friend ostream& operator << (ostream& Str, const FeetInches& FI);
};

#endif // FEETINCHES_H_INCLUDED

Implementation:

#include "FeetInches.h"

FeetInches::FeetInches(int F, int I) {Feet = F; Inches = I;}

int FeetInches::GetInches() const {return Inches;}

int FeetInches::GetFeet() const {return Feet;}

void FeetInches::Simplify()
{
    if (Inches > 0)
    {
        Feet = Feet + (Inches / 12);
        Inches = Inches % 12;
    }
    else if (Inches < 0)
    {
        Feet = Feet - ((abs(Inches) / 12) +1);
        Inches = 12 - (abs(Inches) % 12);
    }
}

const FeetInches& FeetInches::operator = (const FeetInches& FI)
{
    if ((this->Feet != FI.Feet) && (this->Inches != FI.Inches))
    {
        Feet = FI.Feet;
        Inches = FI.Inches;
    }
    return *this;
}

FeetInches& FeetInches::operator + (const FeetInches& FI)
{
    Feet += FI.Feet;
    Inches += FI.Inches;
    this->Simplify();
    return *this;
}

FeetInches& FeetInches::operator - (const FeetInches& FI)
{
    Feet -= FI.Feet;
    Inches -= FI.Inches;
    this->Simplify();
    return *this;
}

ostream& operator << (ostream& Str, const FeetInches& FI)
{
    Str<<FI.Feet<<" feet, "<<FI.Inches<<" inches";
    return Str;
}

very big THX guys!!! Now it works :D, i was frustrating on this..

erm btw about this one, isnt this will change the object's feet and inches?

 FeetInches& FeetInches::operator + (const FeetInches& FI)
 {
 Feet += FI.Feet;
 Inches += FI.Inches;
 this->Simplify();
 return *this;
}

example :
three = one + two.
one's feet and inches will change too right if i use feet+= FI.feet?
please correct me if im wrong.

ok so i removed using namespace std and changed to:

friend std::ostream& operator<<(std::ostream & , const FeetInches &);
friend std::istream& operator>>(std::istream & ,  FeetInches &);

but i really dont get the explanation from http://forums.devshed.com/showpost.php?p=963558&postcount=13 , due to lack of knowledge and also bad english. can u explain the main point why we shhudnt use namespace std inside a header and implementation file?

for now i wont using namespace std everytime i make header and implementation file, and use std:: instead.

three = one + two.
one's feet and inches will change too right if i use feet+= FI.feet?
please correct me if im wrong.

Ahh yes you are correct. Try:

FeetInches FeetInches::operator + (const FeetInches& FI)
{
    FeetInches Temp;
    Temp.Feet += this->Feet + FI.Feet;
    Temp.Inches += this->Inches + FI.Inches;
    Temp.Simplify();
    return Temp;
}

FeetInches FeetInches::operator - (const FeetInches& FI)
{
    FeetInches Temp;
    Temp.Feet -= this->Feet + FI.Feet;
    Temp.Inches -= this->Inches + FI.Inches;
    Temp.Simplify();
    return Temp;
}

As per why not to use namespaces in headers. It's because if two namespaces have a class or function of the same name, the "Using" keyword will cause confusion between which one to "use".

doing Namespace::Function. Will explicitly imply which one to use so that the function does not get mixed up with another one of the same name.

Example:

Two header files have:

Namespace Something1
{
    class string
    {
    };
}

Namespace Something2
{
    class string
    {
    };
}


//As you can see both namespaces contain a class called string.

//If do you do:

using namespace Something1;
using namespace Something2;

//How will the compiler know which string to use?
//Thus to fix this confusion, you do:

Something1::string;  //the compiler knows to use String from the something1 namespace.
Something2::string;  //the compiler knows to use String from the something2 namespace.

from the first time i read c++ ebook bginner i never know why most people dont use "using namespace std" , now i know.
really really thx for the explanation :D

btw if in that case, is it okay to use using std::cout?:

using std::cout;

There is no point to putting "using std::cout". All you need is: "std::cout" The using keyword can be removed.

hmmm ok, after i search about using "using namespace std" is a bad practice since it will confusing if we use another namespace, i think i'll just use the scope for functions

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.