Imagine a class named Poet, with a member FirstName, LastName and class named Verse as Poet's member. is it possible to construct Poet with ifstream, then initialize FirstName and LastName with ifstream, then construct member Verse with the same ifstream? I mean, how can I pass ifstream correctly from one class to it's member class after initializing some members? Thanks.
2 Answers
Step 1: add operator >> to Verse
This is an utterly trivial >>
based on What are the basic rules and idioms for operator overloading?
Since I don't know what's supposed to go inside a Verse
, I'm sticking with the literal definition of one line.
friend std::istream& operator>>(std::istream& in, Verse & obj)
{
std::getline(in, obj.line);
return in;
}
This lets you read from any stream, not just fstream
, into a Verse
. Where it makes sense, work from the highest level of abstraction to get a more general solution.
Step 2: Use Verse
's >>
in the constructor.
I'm flipping a coin over whether or not this is a good thing to do in a constructor. A constructor, like any other function, should do one job. A constructor's job is initialize an object. Reading in from a file may can often overstep the one job rule. Another reason is there are (or should be) only two ways out of a constructor: With an initialized object or a thrown exception and exceptions are expensive. IO has a lot of room for error, so you may find yourself throwing an exception more often than you'd like.
Poet(std::istream & in)
{
in >> FirstName >> LastName >> Verse;
if (!in)
{
throw std::runtime_error("Aaaaaaaarrrggghhhh!");
}
}
Note again I've widened the input stream from a file stream to all istream
s to generalize the function.
Also not the exception if there are any failures reading. You get an object or you don't.
Final note (Baring edits) this solution fails horribly in the face of poet names like "Johann von Goethe" because it will only accept one-word names.

- 33,082
- 7
- 33
- 54
-
-
You can reduce the body of `>>` to `return std::getline(in, obj.line);`. Poet can also get a `>>` in much the same way – Caleth Jan 31 '18 at 14:54
I've found another way. Poet.h:
private:
std::string FirstName;
std::string LastName;
int BirthYear;
bool IsAlive;
int DeathYear;
Verse FirstVerse;
class Poet overloaded constructor in Poet.cpp:
Poet::Poet(std::ifstream & in):DeathYear(0)
{
std::getline(in, FirstName);
std::getline(in, LastName);
in >> BirthYear;
in >> IsAlive;
setDeathYearIfNotAlive(in);
//in >> FirstVerse;
FirstVerse.~Verse();
new(&FirstVerse) Verse(in);
}
Note, that "in" doesn't have overloaded friend operator >>, it's basic std::ifstream in

- 106
- 2
- 10
-
This works too, though is probably not as idiomatic as using the >> operator. You should probably also take an istream rather than an ifstream, like the >> operator does, then you can take any type of input stream, rather than just from a file. – Sean Burton Jan 31 '18 at 16:37
-
Yeah, but `std::ifstream` was a necessary condition of a problem so had to use it. Thanks for letting me know, Sean. – Nick Jan 31 '18 at 20:23