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.

2
  • 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 overloads for fundamental types that actually are member functions, and they're used as building blocks for the free functions for user-defined types. Commented Jun 20, 2022 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. Commented Jun 20, 2022 at 15:01

2 Answers 2

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.
Sign up to request clarification or add additional context in comments.

10 Comments

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?
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.
@WorldTreeBoy Yes, the operators in your example are free functions. Making them friends of your class allows them to access class private members.
@WorldTreeBoy It is a member function not a data member.
@TedLyngmo Yeah, looks better.
|
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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.