* (e-mail address removed), India:
[...]
Breaks the separation-of-concerns design rule. As a general
rule, don't do i/o in constructors. And don't do i/o in
functions or classes that aren't specifically concerned with
i/o.
That probably applies to this type of I/O (and it certainly
applies to std::cout), but I regularly use constructors which
construct objects from persistent store. I think it's a
standard technique when objects should be persistent.
Logging is also appropriate in constructors for application
level classes. Logging definitly involves I/O as well (although
it shouldn't be as direct as this).
The main rationale is the same as for the using directive,
namely, to not force things on client code.
E.g. stream i/o may not be welcome in a GUI application.
In addition, you don't have much control over where
constructors are called (or not).
That's true for objects with value semantics (and then probably
only for the copy constructor), but again, there are large
classes of objects which don't support copy construction. And
of course, the constructor which reads from persistent store is
probably called with the input stream as an argument---you
certainly have total control over where it is called.
Thus, i/o or other side-effects in a constructor is inherently
unreliable.
When reading from persistent store, that's what exceptions are
for (although in specific cases, other strategies may also be
appropriate). When writing to a log, if the write fails, it
fails---your application still works.
Note well that I don't approve outputting to std::cout in a
constructor, at least in production code. I can't ever think of
a case in production code where that would appropriate. (On the
other hand, if you want to write a quick test to see whether
your compiler does NRVO in a specific case...)