Details the overloaded stream insertion operator and stream extraction operator in C++ programming

  • 2020-05-05 11:36:07
  • OfStack

C++ stream insertion operator "<" < "And the stream extraction operator" > > "Is provided by C++ in the class library, where all C++ compilation systems provide the input stream class istream and the output stream class ostream. cin and cout are objects of the istream class and ostream class, respectively. In the header file provided by the class library, "<" has been applied < "And" > > "Has been overloaded as a stream insert operator and a stream extract operator, which can be used to output and input C++ standard types of data. Therefore, always use "cout<" < "And" cin> > "To the standard type of data input and output, to use #include header file included in this program file.

User-defined types of data are not directly used with "< < "And" > > "To output and input. If you want to use them to output and input data of your own declared type, you must overload them.

The "< < "And" > > The overloaded function looks like this:


  istream & operator >> (istream &,  Custom class  &);
  ostream & operator << (ostream &,  Custom class  &);


That is, the overloaded operator "> > The first argument to the function and the type of the function must be istream&, and the second argument is the class to enter. Overloading "< < The first argument to the function and the type of the function must be ostream&, and the second argument is the class to output. Therefore, only ">" can be overloaded > "And" < < "As friend functions or ordinary functions, they cannot be defined as member functions.
overloaded stream insertion operator "< < "

In a program, people want to be able to insert the operator "< < "To output information about the object of the class declared by the user himself, which requires the overloading of the stream-insertion operator" < < ".

Use the overloaded "< < "Output complex Numbers.


#include <iostream>
using namespace std;
class Complex
{
  public:
  Complex( ){real=0;imag=0;}
  Complex(double r,double i){real=r;imag=i;}
  Complex operator + (Complex &c2); // Operator" + "Overloaded as a member function 
  friend ostream& operator << (ostream&,Complex&); // Operator" << "Overloaded as a friend function 
  private:
  double real;
  double imag;
};
Complex Complex::operator + (Complex &c2)// Define the operator" + "Overloaded function 
{
  return Complex(real+c2.real,imag+c2.imag);
}
ostream& operator << (ostream& output,Complex& c) // Define the operator" << "Overloaded function 
{
  output<<"("<<c.real<<"+"<<c.imag<<"i)"<<endl;
  return output;
}
int main( )
{
  Complex c1(2,4),c2(6,10),c3;
  c3=c1+c2;
  cout<<c3;
  return 0;
}

Note that when running in Visual C++ 6.0, the first line is changed to #include < iostream.h > , and delete line 2, otherwise the compilation will not pass. The result is:


(8+14i)

You can see it on the operator "< < "After reloading, use" < "in the program < "Can output not only standard type data, but also the user's own definition of the class object. Use "cout< < c3 "means that the value of the complex object c3 can be printed in the plural form. The form is intuitive, readable and easy to use.

Some instructions on how to implement operator overloading are given below. The operator "<" has been overloaded in the program < ", the parameter output in the operator overload function is a reference to the ostream class object, and the parameter name output is arbitrary by the user. Analyze the last second line of the main function:


  cout<<c3;


"< operator < On the left is cout, which was mentioned earlier as an ostream class object. "< < "On the right is c3, which is an Complex class object. Since the operator "<" has been added < "The overloaded function is declared as the friend function of Complex class < c3 "means


  operator<<(cout, c3)


That is, take cout and c3 as arguments and call operator< below < Function:


  ostream& operator<<(ostream& output,Complex& c)
  {
    output<<"("<<c.real<<"+"<<c.imag<<"i)"<<endl;
    return output;
  }


When a function is called, the parameter output becomes a reference to cout, and the parameter c becomes a reference to c3. So the process of calling a function is equivalent to executing:


cout<< " ( " <<c3.real<< " + " <<c3.imag<< " i) " <<endl; return cout;


Notice that "<" in the previous line < "Is the predefined stream inserter for C++, because the operands to the right of it are string constants and double type data. Execute the cout statement to output information in the plural form. Then execute the return statement.

Think about what return   output does? The answer is to continuously insert information into the output stream. output is an object of class ostream, which is a reference to the argument cout, or cout, which shares the same segment of memory by passing the address to output, or output is an alias for cout. Therefore, return output is return cout, which returns the status of the output stream cout, that is, the status of the output stream.

Where do you want to return to? That was


  cout<<c3;


The known cout< < The return value of c3 is the current value of cout. If you have the following output:


  cout<<c3<<c2;


To deal with first


  cout<<c3


Namely


#include <iostream>
using namespace std;
class Complex
{
  public:
  Complex( ){real=0;imag=0;}
  Complex(double r,double i){real=r;imag=i;}
  Complex operator + (Complex &c2); // Operator" + "Overloaded as a member function 
  friend ostream& operator << (ostream&,Complex&); // Operator" << "Overloaded as a friend function 
  private:
  double real;
  double imag;
};
Complex Complex::operator + (Complex &c2)// Define the operator" + "Overloaded function 
{
  return Complex(real+c2.real,imag+c2.imag);
}
ostream& operator << (ostream& output,Complex& c) // Define the operator" << "Overloaded function 
{
  output<<"("<<c.real<<"+"<<c.imag<<"i)"<<endl;
  return output;
}
int main( )
{
  Complex c1(2,4),c2(6,10),c3;
  c3=c1+c2;
  cout<<c3;
  return 0;
}
0


To execute (cout< < The result of c3 is a stream object cout with new content, therefore, (cout<) < c3) < < c2 is equivalent to cout(new value)< < c2. "< operator < "ostream class object cout on the left, c2 on the right, then call the operator" < again < "Overload the function, then insert the data of c2 into the output stream. Now you can understand why C++ specified operator "< < "The first argument to an overloaded function and the type of the function must be a reference of type ostream in order to return the current value of cout for continuous output.

Please note the difference between "<" and "<" < "Is a stream inserter for data of standard types, in what case is" < < "Is an overloaded stream inserter. Such as


#include <iostream>
using namespace std;
class Complex
{
  public:
  Complex( ){real=0;imag=0;}
  Complex(double r,double i){real=r;imag=i;}
  Complex operator + (Complex &c2); // Operator" + "Overloaded as a member function 
  friend ostream& operator << (ostream&,Complex&); // Operator" << "Overloaded as a friend function 
  private:
  double real;
  double imag;
};
Complex Complex::operator + (Complex &c2)// Define the operator" + "Overloaded function 
{
  return Complex(real+c2.real,imag+c2.imag);
}
ostream& operator << (ostream& output,Complex& c) // Define the operator" << "Overloaded function 
{
  output<<"("<<c.real<<"+"<<c.imag<<"i)"<<endl;
  return output;
}
int main( )
{
  Complex c1(2,4),c2(6,10),c3;
  c3=c1+c2;
  cout<<c3;
  return 0;
}
1


Underlined is the calling overloaded stream inserter, followed by "<" < "Is not an overloaded stream inserter because its right-hand side is not an Complex class object but a standard type of data, which is handled with predefined stream inserters.

One more thing to note is that in this program, the operator "<" is defined in the Complex class < An overloaded function is a friend function, so the overloaded operator can only be used when an Complex class object is output. It is not valid for other types of objects. Such as


#include <iostream>
using namespace std;
class Complex
{
  public:
  Complex( ){real=0;imag=0;}
  Complex(double r,double i){real=r;imag=i;}
  Complex operator + (Complex &c2); // Operator" + "Overloaded as a member function 
  friend ostream& operator << (ostream&,Complex&); // Operator" << "Overloaded as a friend function 
  private:
  double real;
  double imag;
};
Complex Complex::operator + (Complex &c2)// Define the operator" + "Overloaded function 
{
  return Complex(real+c2.real,imag+c2.imag);
}
ostream& operator << (ostream& output,Complex& c) // Define the operator" << "Overloaded function 
{
  output<<"("<<c.real<<"+"<<c.imag<<"i)"<<endl;
  return output;
}
int main( )
{
  Complex c1(2,4),c2(6,10),c3;
  c3=c1+c2;
  cout<<c3;
  return 0;
}
2


overloaded stream extraction operator "> > "

C++ predefined operator ">" > Is used to extract data from an input stream, such as "cin> > i;" Indicates that an integer is extracted from the input stream and assigned to the variable i(assuming that i is of type int). The purpose of the overloaded stream extraction operator is to want ">" > "To enter information about objects of a custom type.

On the basis of the above example, the overloaded stream extraction operator ">" is added > ", use "cin> > "Enter complex Numbers, using" cout< < "Output complex Numbers.


#include <iostream>
using namespace std;
class Complex
{
  public:
  friend ostream& operator << (ostream&,Complex&); // Declare overloaded operator" << " 
  friend istream& operator >> (istream&,Complex&); // Declare overloaded operator" >> " 
  private:
  double real;
  double imag;
};
ostream& operator << (ostream& output,Complex& c) // Define the overloaded operator" << " 
{
  output<<"("<<c.real<<"+"<<c.imag<<"i)";
  return output;
}
istream& operator >> (istream& input,Complex& c) // Define the overloaded operator" >> " 
{
  cout<<"input real part and imaginary part of complex number:";
  input>>c.real>>c.imag;
  return input;
}
int main( )
{
  Complex c1,c2;
  cin>>c1>>c2;
  cout<<"c1="<<c1<<endl;
  cout<<"c2="<<c2<<endl;
  return 0;
}

Here's how it works:


#include <iostream>
using namespace std;
class Complex
{
  public:
  Complex( ){real=0;imag=0;}
  Complex(double r,double i){real=r;imag=i;}
  Complex operator + (Complex &c2); // Operator" + "Overloaded as a member function 
  friend ostream& operator << (ostream&,Complex&); // Operator" << "Overloaded as a friend function 
  private:
  double real;
  double imag;
};
Complex Complex::operator + (Complex &c2)// Define the operator" + "Overloaded function 
{
  return Complex(real+c2.real,imag+c2.imag);
}
ostream& operator << (ostream& output,Complex& c) // Define the operator" << "Overloaded function 
{
  output<<"("<<c.real<<"+"<<c.imag<<"i)"<<endl;
  return output;
}
int main( )
{
  Complex c1(2,4),c2(6,10),c3;
  c3=c1+c2;
  cout<<c3;
  return 0;
}
4

The above results are undoubtedly correct, but not perfect. When the imaginary part of the input complex number is positive, the output result is ok, but if the imaginary part is negative, it is not ideal. Please observe the output result.


#include <iostream>
using namespace std;
class Complex
{
  public:
  Complex( ){real=0;imag=0;}
  Complex(double r,double i){real=r;imag=i;}
  Complex operator + (Complex &c2); // Operator" + "Overloaded as a member function 
  friend ostream& operator << (ostream&,Complex&); // Operator" << "Overloaded as a friend function 
  private:
  double real;
  double imag;
};
Complex Complex::operator + (Complex &c2)// Define the operator" + "Overloaded function 
{
  return Complex(real+c2.real,imag+c2.imag);
}
ostream& operator << (ostream& output,Complex& c) // Define the operator" << "Overloaded function 
{
  output<<"("<<c.real<<"+"<<c.imag<<"i)"<<endl;
  return output;
}
int main( )
{
  Complex c1(2,4),c2(6,10),c3;
  c3=c1+c2;
  cout<<c3;
  return 0;
}
5

According to the principle of first debugging through, the last perfect, can make necessary changes to the program. Will override the operator "< < The function is modified as follows:


#include <iostream>
using namespace std;
class Complex
{
  public:
  Complex( ){real=0;imag=0;}
  Complex(double r,double i){real=r;imag=i;}
  Complex operator + (Complex &c2); // Operator" + "Overloaded as a member function 
  friend ostream& operator << (ostream&,Complex&); // Operator" << "Overloaded as a friend function 
  private:
  double real;
  double imag;
};
Complex Complex::operator + (Complex &c2)// Define the operator" + "Overloaded function 
{
  return Complex(real+c2.real,imag+c2.imag);
}
ostream& operator << (ostream& output,Complex& c) // Define the operator" << "Overloaded function 
{
  output<<"("<<c.real<<"+"<<c.imag<<"i)"<<endl;
  return output;
}
int main( )
{
  Complex c1(2,4),c2(6,10),c3;
  c3=c1+c2;
  cout<<c3;
  return 0;
}
6


Thus, the last behavior of the runtime output, c2=(4-10i).

As you can see, operator overloading is important and useful in C++. It makes the design of the class more colorful, expanded the function and use of the scope of the class, make the program easy to understand, easy to operate on the object, it embodies the user for the sake of the user, convenient to use the idea. With operator overloading, after declaring the class, people can use their declared class as if it were a standard type. Class declaration is often once and for all, with a good class, the user in the program does not have to define many member functions to complete some operations and input and output functions, making the main function more simple and easy to read. Good operator overloading embodies the idea of object-oriented programming.

You can see the importance of using references (reference) in operator overloads. Using a reference as a parameter of a function can make the parameter an alias of an argument in the process of calling a function instead of passing a value, so it does not generate a temporary variable (a copy of an argument), which reduces the overhead of time and space. In addition, if the return value of an overloaded function is a reference to an object, instead of a constant, it returns the object represented by the reference. It can appear to the left of the assignment number and become an lvalue (left value), be assigned or participate in other operations (such as keeping the current value of the cout stream so that "<" can be used continuously < "Output). Be careful with references, however, because changing a reference is like changing the object it represents.


Related articles: