pexea12
pexea12

Reputation: 1209

Problems with istream& operator >>

I am still wondering about istream operator>>. In my function istream& operator >> (istream &is, Student& a), I didn't use is but still return it at the end of the function. I still get the correct answer with cin >> a. Can anyone explain why?

#include <iostream>

using namespace std;

class Student
{
private:
    int age;
public:
    Student() : age(0){}
    Student (int age1) : age(age1) {}
    void setAge();
    int getAge(){return age;}
    friend istream& operator >> (istream& is, Student& a);
};

istream& operator >> (istream &is, Student& a)
{
    a.setAge();
    return is;
}
void Student::setAge(){
    int age1;
    cout << "input age of the student: "<< endl;
    cin >> age1;
    age = age1;
}

int main()
{
    Student a;
    cin >> a;
    cout << "Age of Student is " << a.getAge() << "?";
}

Upvotes: 1

Views: 1238

Answers (4)

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385264

I didn't use is

Yes you did. You just used it from a different function, is all.

It's the same stream because it's cin in both cases.

If you ever wanted to extract from a different stream then your code would be broken. This is why we prefer to use the argument to operator>> rather than sort of guessing at what it was (cin).

Upvotes: 0

radato
radato

Reputation: 930

Actually there are quite a few points to make in your example.

Firstly a setter should have a parameter. By convention, a setter always gets a parameter which alters the class and then the getter is parameterless and should be const.

Secondly, your implementation of setAge directly accesses std::cin. If you look at my example you will see that I do make use of the is parameter. That separates the setAge from the source of the parameter and allows for better OOD.

Thirdly, my implementation also provides better abstraction because the input stream is could be any stream (for example a file, or maybe a stream from the internet)

#include <iostream>

using namespace std;

class Student
{
private:
    int age;
public:
    Student() : age(0){}
    Student(int age1) : age(age1) {}
    void setAge(int age1);
    int getAge() const { return age; }
    friend istream& operator >> (istream& is, Student& a);
};

istream& operator >> (istream &is, Student& a)
{
    int age1;
    is >> age1;
    a.setAge(age1);
    return is;
}
void Student::setAge(int age1){
    age = age1;
}

int main(int argc, char* argv[])
{
    Student a;
    cout << "input age of the student: " << endl;
    cin >> a;
    cout << "Age of Student is " << a.getAge() << "?" << endl;

    return 0;
}

Upvotes: 0

Remy Lebeau
Remy Lebeau

Reputation: 597036

In my function istream& operator >> (istream &is, Student& a), I didn't use is but still return it at the end of the function. I still get the correct answer with cin >> a. Can anyone explain why?

Because Student::setAge() is accessing cin directly, which is the same stream that is happens to be pointing at in your example.

This is not the correct design. A member setter should not be prompting the user for input. You should prompt for input first, then pass the value to your setter afterwards. The class should be agnostic about where its values are coming from.

Use something more like this instead:

#include <iostream>

using namespace std;

class Student
{
private:
    int age;
public:
    Student() : age(0){}
    Student (int age1) : age(age1) {}
    void setAge(int value);
    int getAge(){return age;}
    void readFrom(istream& is);
};

istream& operator >> (istream &is, Student& a)
{
    a.readFrom(is);
    return is;
}

void Student::readFrom(istream& is){
    is >> age;
}

void Student::setAge(int value){
    age = value;
}

int main()
{
    Student a;
    int age;
    cout << "input age of the student: "<< endl;
    cin >> age;
    a.setAge(age);
    cout << "Age of Student is " << a.getAge() << "?";
}

Upvotes: 2

user93353
user93353

Reputation: 14039

This works fine because you are calling

cin >> a;

If instead you did this

ifstream ifs ("test.txt", ifstream::in);
ifs >> a;

Then your program will read from standard input instead of the file (test.txt) like it's supposed to be doing.

The correct implementation would be

istream& operator >> (istream &is, Student& a)
{
    return is >> a.age;
}

Now if you call

cin >> a;

it would read from standard input

and if you call

ifs >> a;

it would read from the file.

Upvotes: 5

Related Questions