user3249265
user3249265

Reputation: 113

Overloading input operation >> in header or .cpp

If i want to overload the operator ">>" and this is the line inside my .h file

  friend istream &operator >> (istream& input,const Money&m2);

Do I want for instance

  friend istream &operator >> (istream& input,const Money&m2){
    input >> m2.dollar;
    return input;
}

into my header file or into my class file. If i were to put it into my class file how would the function be called? Would something like this be okay?

  const Money Money::&operator >> (istream& input,const Money&m2)

The class name is "Money.cpp"

Upvotes: 2

Views: 3487

Answers (4)

Andrew
Andrew

Reputation: 5352

The input streaming operator takes a reference to a non-const std::istream, and a reference to a non-const object into which the data is to be read. You can define it as a friend of the class for efficiency (direct access to the member variables), but if you already provide efficient mechanisms for setting those values, you may want to consider whether it needs to be a friend at all.

In the example below, I define a class Money, which represents some value (as a double-precision floating-point value, which is pretty bad, but just an example) and the ISO currency code (as a std::string). I then define an input streaming operator that reads input in the format "13.99 GBP" and an output streaming operator that writes the values in the same format.

Live example: http://coliru.stacked-crooked.com/a/d3e24b4fd697f773

money.hpp

class Money {
  public:
    Money(double value, const std::string& code);

    const std::string& currencyCode() const;
    double value() const;

    friend std::istream& operator>>(std::istream&, Money&);
  private:
    double value_;
    std::string code_;
};

std::istream& operator>>(std::istream& in, Money& m);
std::ostream& operator<<(std::ostream& out, const Money& m);

money.cpp

Money::Money(double value, const std::string& code)
     : value_(value), code_(code) {}

const std::string& Money::currencyCode() const {
  return code_;
}

double Money::value() const {
  return value_;
}

std::istream& operator>>(std::istream& in, Money &m) {
  in >> m.value_ >> m.code_;
  return in;
}

std::ostream& operator<<(std::ostream& out, const Money& m) {
  out << m.value() << " " << m.currencyCode();
  return out;
}

Some points to bear in mind:

  • In general, the output streaming operator need not be a friend; there is usually a way to access the information it needs through the public member functions of the class, without losing efficiency.
  • The input streaming operator is a friend only for efficiency reasons; we can stream directly into the member variables.
  • For the input streaming operator, the second parameter (the object you're reading into) must not be const - an input operation changes the object being read into.
  • For the output streaming operator, the second parameter (the object you're writing out) should be const - an output operation should not change the object being written out.

If the constructor performs some non-trivial validation (e.g. checking that the std::string contains a valid ISO currency code), we should not bypass that validation by reading directly into the member variable in our input streaming operator. Instead, we should read into a local double and a local string, then construct a Money object, handing validation off to the already-written constructor (see the example below; the header is identical, except for removing the friend declaration from the class).

Live example: http://coliru.stacked-crooked.com/a/233ac7c17e51f612

money.cpp (validation in constructor)

Money::Money(double value, const std::string& code)
     : value_(value), code_(code) {
 if (code_ != "GBP") throw std::runtime_error("Must be GBP");
}

const std::string& Money::currencyCode() const {
  return code_;
}

double Money::value() const {
  return value_;
}

std::istream& operator>>(std::istream& in, Money &m) {
  double value(0.0);
  std::string code;
  in >> value >> code;
  m = Money(value, code);
  return in;
}

std::ostream& operator<<(std::ostream& out, const Money& m) {
  out << m.value() << " " << m.currencyCode();
  return out;
}

Upvotes: 3

Rupesh Yadav.
Rupesh Yadav.

Reputation: 904

I don't know what is bothering you so have this example and see if it clears your doubt.
Run Here: http://ideone.com/K90L13

.h

#include <iostream>
#include <istream>
using namespace std;

class A{
    int p;
public:
    friend istream & operator >> (istream&,A&);
    friend ostream & operator << (ostream&,A&);
};

.cpp

istream & operator >> (istream &input, A &obj){
    input >> obj.p;
    return input;
}
ostream & operator << (ostream &output, A &obj){
    output << obj.p;
    return output;
}
int main(){
    A a;
    cin >> a;
    cout << a;
}

Upvotes: 0

Paul Evans
Paul Evans

Reputation: 27577

If you put it in your header any change in the function definition requires recompilation of any files that include it. If you define it in the .cpp file then you don't and the linker will sort out calling it.

Upvotes: 0

user3249265
user3249265

Reputation: 113

answered.

Function name in class field should be

std::istream &operator >> (istream& input,const Money&m2){}

Upvotes: -1

Related Questions