Search code examples
c++idiomsostreaminitialization-list

Base-from-Member Idiom in C++


The following code is from here:

#include <streambuf>  // for std::streambuf
#include <ostream>    // for std::ostream

class fdoutbuf
    : public std::streambuf
{
public:
    explicit fdoutbuf( int fd );
    //...
};

class fdostream
    : public std::ostream
{
protected:
    fdoutbuf buf;
public:
    explicit fdostream( int fd ) 
        : buf( fd ), std::ostream( &buf ) // This is not allowed. 
                                          // buf can't be initialized before std::ostream.
        {}
    //...
};

I didn't really understand the comment. Why "buf can't be initialized before std::ostream"? Can I use some help understanding this?


Solution

  • The order of initialization is determined by the order of declaring your class members, and inherited classes come before all of that. Take a simple example that illustrate the basic problem without referring to inheritance :

    class C
    {
      int a, b;
    public:
      C() : b(1), a(b) {} // a is initialized before b!
    };
    

    The code doesn't do what you think! a is initialized first, then b is initialized to one. So it depends on the order of the declaration not the order in the initialization list:

    int a, b;
    

    Now, the same idea applies to base classes which are initialized before the derived class members. To solve this problem, you create a class that you inherent which contains the member you want to initialize from a base class. Of course, that helper class must come before the one you are actually deriving from.