In Section 17.3.2 we saw how to derive a new stream class. In Section 18.2 we saw how to derive a streambuf class, and an example of how to connect the two. In this section, we'll look a little more closely at the ways the two can be connected together safely.
This connection can be attempted in two different ways:
By deriving from a descendent of ios which does not have a streambuf, such as istream or ostream, and providing it with an external streambuf which is itself a derived type.
By deriving from a descendent of ios which provides a streambuf, such as ifstream or ofstream.
In the first case where the stream does not have a buffer, the ANSI/ISO standard mandates that no parent class constructors or destructors (ios, istream, or ostream) access the stream buffer. This restriction is important, since a derivation such as the following is otherwise unsafe:
class DerivedStreamBuf : public streambuf { // .... }; class DerivedOutputStream : public ostream { public: DerivedOutputStream():ostream(&dsb):ios(0){} // 1 // .... private: DerivedStreamBuf &dsb; // .... };
//1 | The DerivedOutputStream constructor calls its parent constructors in the following order:
ios() ostream(&dsb) DerivedStreamBuf () DerivedOutputStream() |
Looking at this order, we can see that ios and ostream were constructed before DerivedStreamBuf() was executed. Therefore the pointer (&dsb) passed through the ostream constructor is essentially an invalid pointer, and accessing it would be catastrophic. In the case where the derived stream has a buffer, only the descendent who provides the buffer can access it during construction or destruction. In both cases, explicitly preventing access to the stream buffer by the base class during the construction and destruction phases prevents catastrophic consequences.
OEM Edition, OEM Edition, ©Copyright 1999, Rogue Wave Software, Inc.
Contact Rogue Wave about documentation or support issues.