0

From c++ how to program 10th edition by deitel


//Fig. 10.3: PhoneNumber.h
//PhoneNumber class definition
#ifndef PHONENUMBER_H
#define PHONENUMBER_H

#include <iostream>
#include <string>

class PhoneNumber
{
    friend std::ostream& operator<<(std::ostream&, const PhoneNumber&);
    friend std::istream& operator>>(std::istream&, PhoneNumber&);

private:
    std::string areaCode; //3-digit area code
    std::string exchange; //3-digit exchange
    std::string line; //4-digit line
};
#endif // PHONENUMBER_H
//Fig. 10.4: PhoneNumber.cpp
//Overloaded stream insertion and stream extraction operators
#include <iomanip>
#include "PhoneNumber.h"
using namespace std;

//overloaded stream insertion operator; cannot be a member function
//if we would like to invoke it with cout << somePhoneNumber;

ostream& operator<<(ostream& output, const PhoneNumber& number)
{
    output << "Area code: " << number.areaCode << "\nExchange: "
        << number.exchange << "\nLine: " << number.line << "\n"
        << "(" << number.areaCode << ") " << number.exchange << "-"
        << number.line << "\n";
    return output; //enables cout << a << b << c;
}

//overloaded stream extraction operator; cannot be a member function
//if we would like to invoke it with cin >> somePhoneNumber;
istream& operator>>(istream& input, PhoneNumber& number)
{
    input.ignore(); //skip (
    input >> setw(3) >> number.areaCode; //input area code
    input.ignore(2); //skip ) and space
    input >> setw(3) >> number.exchange; //input exchange
    input.ignore(); //skip dash (-)
    input >> setw(4) >> number.line; //input line
    return input; //enables cin >> a >> b >> c
}

//Fig. 10.5: fig10_5.cpp
//Demonstrating Class PhoneNumber's overloaded stream insertion
//and stream extraction operators.

#include <iostream>
#include "PhoneNumber.h"
#include <string>

using namespace std;

int main()
{
    PhoneNumber phone; //create object phone

    cout << "Enter phone number in the form (555) 555-5555:" << endl;

    //cin >> phone invokes operator>> by implicitly issuing
    //the non-member function call operator>>(cin, phone)
    cin >> phone;

    //cout << phone invokes operator<< bby implicitly issuing
    //the non-member function call operator<<(cout, phone)
    cout << phone << endl;
}

I understand from the book that the overloaded operator function for binary operator can be member function only when the left operand is an object of the class in which the function is a member because the member function can only be accessed by left operand which is the object of the class.

however I don't understand this part

" The overloaded stream insertion operator (<<) is used in an expression in which the left operand has type ostream&, as in cout << classObject. To use the operator in this manner where the right operand is an object of a user-defined class, it must be overloaded as a non-member function. To be a member function, operator << would have to be a member of class ostream. This is not possible for user-defined classes, since we are not allowed to modify C++ Standard Library classes. "

my question is

  1. whether the stream extraction and insertion operator is part of the ostream and istream respectively?
  2. what does the part highlighted in bold mean?

My guess is that we cannot add user defined function into the C++ Standard Library class but the part in bold makes me kind of confused. do we have to add the operator << as member of class ostream to make the overloaded operator function as member function of ostream?

I always thought that stream << and >> operator were part of ostream and istream respectively.

Correct me if I am wrong. thank you in advance.

  • You can't add anything directly to the `std::basic_ostream` class template. That means you can't add a new overload of `operator<<`. That's _why_ `operator<<` for streams isn't implemented as a member function. Instead of `std::basic_ostream::operator<<(SomeType)`, it's `operator<<(std::ostream&, SomeType)`, because you _are_ allowed to write new free functions. There are a [few](https://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt) overloads for fundamental types that actually are member functions, and they're used as building blocks for the free functions for user-defined types. – Nathan Pierson Jun 20 '22 at 12:55
  • I often use free standing header file `inline std::ostream& operator<<(std::ostream& out, const PhoneNumber& pn) { pn.print(out); return out; }` and then have a member function `void print(std::ostream& out) const;`. No need for `friend` that way. And if you use polymorphism, make `print` a `virtual` member function. Easy peasy. – Eljay Jun 20 '22 at 15:01

2 Answers2

1
  1. No, not for regular user defined types. The functions you made into friends in your class definition are free functions:
    std::ostream& operator<<(std::ostream&, const PhoneNumber&);
    std::istream& operator>>(std::istream&, PhoneNumber&);
    
    std::basic_ostream does have some operator<< member overloads for fundamental types, such as int, and some types defined in the standard library though. If you inherit from some of those standard types, like std::basic_streambuf<CharT, Traits>, you will be able to use the basic_ostream::operator<< member overloads for those types.
  2. It means that you are not allowed to modify the definition of std::basic_ostream to add std::basic_ostream& operator<<(const PhoneNumber&) as a member function.
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • You mean the stream insertion and extraction operator are not part of any class? they are free just like + - / * operator? meaning they are not bounded to any classes? – WorldTreeBoy Jun 20 '22 at 13:01
  • 1
    Most operators for user-defined types can be implemented as either free functions or as class member functions and which way you choose depends on how you want to do it. Some operators like the assignment operator `operator=` can only be implemented as member functions. Some operators like `operator<<` where the left hand side is a `std::ostream` and the right hand side is a user-defined type must be implemented as free functions. – Nathan Pierson Jun 20 '22 at 13:06
  • @WorldTreeBoy Yes, the operators in your example are free functions. Making them `friend`s of your class allows them to access class private members. – Ted Lyngmo Jun 20 '22 at 13:09
  • @TedLyngmo The first part of the answer is incorrect assuming by writing `1)` you're answering the first question asked by OP. As `ostream` does have `operator<<` as member functions. I was about to answer but then found a dupe that explains this. – Jason Jun 20 '22 at 13:15
  • @AnoopRana Answering while on the tram. I'm soon at home and will take a closer look :-) – Ted Lyngmo Jun 20 '22 at 13:24
  • @AnoopRana is << operator a data member or a member function in the ostream and istream class? because the book says "operator << would have to be a member of class ostream." as highlighted in the bolded part. – WorldTreeBoy Jun 20 '22 at 13:30
  • 1
    @WorldTreeBoy It is a member function not a data member. – Jason Jun 20 '22 at 13:31
  • @AnoopRana thanks. the book should have phrased it better. – WorldTreeBoy Jun 20 '22 at 13:34
  • @AnoopRana Edited. I hope it made it clearer. – Ted Lyngmo Jun 20 '22 at 13:39
  • 1
    @TedLyngmo Yeah, looks better. – Jason Jun 20 '22 at 13:50
0

You might have already read about overloading. There is not one function called operator<<, there are multiple. Some of those are class members, others aren't. The compiler will choose the right operator<< based on the two arguments.

When the compiler looks for overloads of operator<<, it will check class methods of the object on the left-hand side only. (If that's even a class. In 1<<3==8 the arguments are ints). For that reason, when the compiler sees std::cout << YourClass{} it won't look for YourClass::operator<<(ostream&).

If you wrote YourClass{} << std::cout (VERY unusual), the compiler would look in YourClass. Rules are rules, and there is no hard rule that forbids that order. But it would break the usual chaining of std::cout << a << b << c, so it's very inconvenient. So to make the usual chaining work, we do it as your textbook tells you.

MSalters
  • 173,980
  • 10
  • 155
  • 350