3

Trying to study C++ function templates. As a part of which I have this code below. It works fine, but I have questions as below :-

1] Why is the operator << overloading function need to be friend ? If I remove the keyword friend it gives compilation error saying : operator << has too many parameters.

2] Why does the operator << overloading function need to return a reference to ostream object which is also an input argument to it?

3]I doubt this, but Do the above 2 questions have got anything to do with the fact that the function templates are used for a user defined class which has overloaded functions?

template <class T>
T Average(T *atArray, int nNumValues)
{
    T tSum = 0;
    for (int nCount=0; nCount < nNumValues; nCount++)
        tSum += atArray[nCount];

    tSum /= nNumValues;
    return tSum;
}

class Cents
{
private:
    int m_nCents;
public:
    Cents(int nCents)
        : m_nCents(nCents)
    {
    }

    //Why is friend needed below

    //Why does it need to return ostream&, why can't it have void return type, as all it is doing is printing the class private member.
    friend ostream& operator<< (ostream &out, const Cents &cCents)
    {
        out << cCents.m_nCents << " cents ";
        return out;
    }

    /* 
    void operator <<( const Cents &cCents) //did not work - compilation errors
    {
        cout << cCents.m_nCents << " cents ";
    }
    */

    void operator+=(Cents cCents)
    {
        m_nCents += cCents.m_nCents;
    }

    void operator/=(int nValue)
    {
        m_nCents /= nValue;
    }
};

int main()
{
    int anArray[] = { 5, 3, 2, 1, 4 };
    cout << Average(anArray, 5) << endl;

    double dnArray[] = { 3.12, 3.45, 9.23, 6.34 };
    cout << Average(dnArray, 4) << endl;

    Cents cArray[] = { Cents(5), Cents(10), Cents(15), Cents(14) };
    cout << Average(cArray, 4) << endl;

    cin.get();
    return 0;
}
Christian Rau
  • 45,360
  • 10
  • 108
  • 185
goldenmean
  • 18,376
  • 54
  • 154
  • 211

3 Answers3

3

Why is the operator << overloading function need to be friend ? If I remove the keyword friend it gives compilation error saying : operator << has too many parameters.

<< alters the stream’s state, and hence ideally it should be implemented as member of it's left operand’s type. However, its left operands are streams from the standard library, and while most of the stream output and input operators defined by the standard library are indeed defined as members of the stream classes, when you implement output and input operations for your own types, you cannot change the standard library’s stream types.
That is why you need to implement these(<< and >>) operators for your own types as non-member functions. Since you need to access the private/protected member variables of your class object inside the operator definition, these overloaded operators are needed to be declared as friend of your class.

Why does the operator << overloading function need to return a reference to ostream object which is also an input argument to it?

Returning an reference to standard stream object allows you to have Object Chaining.

You can have calls like:

out<<obj1<<obj2;

Templates are used for a user defined class which has overloaded functions?

Templates help you implement generic functions and classes which can be called for different datatypes and the compiler takes care of generating the code for those specific data types. So the above two points are not related.


Strongly suggest reading this FAQ entry:
Operator overloading

Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • thanks. One doubt I have is why can't oeprator >> be a class member function. Because finally thats what I am going to use operator << with, object of user defined class, isn't it. Why it needs to be a non-member/general function? – goldenmean Sep 19 '11 at 16:06
  • @goldenmean: The first part of my answer touches upon that, and You should read through the link I added to the answer that will help you understand this in much better way and solve the doubt you have as well. – Alok Save Sep 19 '11 at 16:21
1

[1] It needs to be friend because it tries to access the private member variable m_nCents, that is only accessible to member functions of Cents or to friends of Cents.

[2] That is the standard function signature for overloading the "streaming operators". This makes it possible to concatenate <<s:

out << a << b;

which is equivalent to

(out << a) << b;

EDIT: It seems you want the operator<< to be a member of the class. This is not possible, as it's first operand is an ostream and not a Cents. The friend actually declares it as a non-member friend function. If you leave the friend keyword away, you declare it as member function (as it's inside the class definition), but in this case it has too many arguments (the two in the signature, and the implicit Cents as first argument, the one it's called on, the this pointer if you like).

Declaring the operator<< for streaming as a non-member function is the standard way to do it, either friend or not (depends, in your case you need friend, or you make m_nCents publicly available somehow).

Christian Rau
  • 45,360
  • 10
  • 108
  • 185
0

It must return an ostream and take one as a parameter so you can chain multiple calls together.

Eg:

Cents a,b,c;
cout << a << b << c;

It has to be a friend because it's not a member function, regardless of the fact that you defined inside the class block of code.

Let me expand on this concept. The above example is equivalent to the following:

op(op(op(cout,a),b),c);

Where 'op' is shorthand for the actual function name of the overloaded operator. Note that it is not called on an instance of Cents, and in fact will have no this ptr because it exists outside the class just like a stand-alone function.

Brian McFarland
  • 9,052
  • 6
  • 38
  • 56