Reputation: 1223
I know this is pretty basic but I've kind of been guessing up to this point.
Foo is just an object with private inheritance from the string class which is why I cast it. Using examples from Primer C++ (Prata's)
So if I have a function like:
istream & operator>>(istream & is, Foo & f)
{
is >> (string &)f;
return is;
}
int main()
{
Foo f;
cin >> f;
}
So, once cin >> f is hit, the function is called and the now string is stored in the istream reference. The istream object is now returned and now...? Is the returned istream object's content (the string) now placed automatically within f? Or did I miss a step in understanding how cin works?
Also, if I were to do:
int x;
cin >> f >> x;
How would it implicitly look like? Like (cin) >> x?
Finally, one more simple thing. If in a function (which contains an ostream reference) I am in a loop passing over every array item and doing this:
for(int i=0;i < 5;i++)
{
os << array[i] << "\n";
}
Is the ostream object just compounded each array item within itself?
Upvotes: 1
Views: 3854
Reputation: 355059
When you do cin >> f
, overload resolution selects your overloaded istream >>
overload and calls it. Then, in your overload, you extract a string
from the stream, which calls the >>
overload that takes an istream and a string
.
Note that it is most unusual to derive from std::string
, even privately. Instead, you should probably use composition: have a member variable of type std::string
.
The cast you have is quite confusing; if you had a member variable of type std::string
instead, then you could extract that using much more natural syntax:
is >> f.stringmembervariable;
cin >> f >> x
first extracts a Foo
from cin
and stores it in f
, then extracts an int
from cin
and stores it in x
. Assuming that all of the >>
overloads follow the convention of returning the istream they are passed, it is effectively the same as if you were to say:
cin >> f;
cin >> x;
This is why you should return the istream from the >>
overload, so that the extractions can be chained like this.
As for your last question, inside the loop the overloaded ostream <<
operator is called for whatever the type of array[i]
is.
Upvotes: 1
Reputation: 35141
istream & operator>>(istream & is, Foo & f)
{
is >> (string &)f;
return is;
}
istream& operator>>(istream& is, string& f)
(well, basic_istream<T>&, basic_sttring<T>&
) already exists. So while you can do this, why do it?
So, once cin >> f is hit, the function is called and the now string is stored in the istream reference
No, the stream is consumed by istream& operator>>(istream& is, string& f)
, which sets the string ('s storage) to contain a representation of the consumed bytes.
Then a reference to the istream is returned.
int x;
cin >> f >> x;
is equivalent to:
int x;
(cin >> f) >> x;
because of operator associativity rules, and is "really":
int x;
std::operator>>( ::operator>>(cin, f), x ) ;
where the two operator>>
s are two different overloaded versions of op>>
, that is, your version (in the global namespace) that takes an istream and a Foo is the inner one, which return a reference to istream, which is in the turn the first argument of the outer one, the one in std namespace that takes an istream and an int.
Is the ostream object just compounded each array item within itself?
Each object, of whatever type array[n] is, is added to the ostream, in sequence, to the stream, follows by a newline. So "compunded" is a bad way to express it, but yes. Naturally, there needs to exist an op<<( ostream&, const X&)
where "X" is whatever type array[n] is (or is implicitly convertible to).
Upvotes: 1
Reputation: 70701
It becomes very easy if you replace the overloaded operators with normal function calls. cin >> f
simply translates to:
operator >>(cin, f);
Now think of cin >> f >> x
as (cin >> f) >> x
. This translates to:
operator >>(operator >>(cin, f), x);
Since the first operator returns cin
, during execution, this actually becomes:
operator >>(cin, x);
Primitive data types such as int
are generally overloaded within the stream class itself, so it actually looks like this:
cin.operator >>(x);
You can extend this by yourself to answer your question about ostream
- it works exactly the same way.
Upvotes: 3
Reputation: 746
When you do:
cin >> f;
you are correct in that your operator function will be called, and whatever string was on cin would now be stored in f.
When you do:
cin >> f >> x;
what really happens is that your function is called the same as before, but then it returns cin. Since there is no overloaded >> defined for an istream and an int, cin would be processed normally.
So first, the computer would compute:
cin >> f;
which gets overloaded by your function. And then the computer computes:
cin >> x;
which is the normal operation for cin and an integer.
The same thing happens with your line:
os << array[i] << "\n";
in that:
os << array[i];
gets processed first, and then:
os << "\n";
gets processed.
Technically, in both cases, your stream object gets returned, but there's nothing using the returned value, so it's just discarded. It would be the same thing as a line that said:
sqrt(81);
Since there's no variable to store the returned value, the computer will compute the value and then just discard it (or skip it entirely if your compiler is smart).
Upvotes: 0