More C++ Idioms/メンバによる基本クラスの初期化(Base-from-Member)

メンバによる基本クラスの初期化(Base-from-Member)
編集

意図 編集

派生クラスのデータメンバによって基本クラスを初期化する。

別名 編集

動機 編集

派生クラス、あるいはそのクラスのデータメンバによって基本クラスを初期化することが必要になる場合がある。これは、データメンバのコンストラクタ(が存在するならばその)実行前に、基本クラスが初期化されるという C++ の規格に反しているように聞こえる。このイディオムは、パラメータとなるデータメンバを private な基本クラスに押し込み、基本クラスのリスト中でその private な基本クラスを、依存する基本クラスよりも前に置くというものである。規格では、常に、基本クラスのリスト中に宣言された順序で、基本クラスが初期化されることが定められている。

解法とサンプルコード 編集

以下のコードは、Boost[1]ライブラリから持ってきたものである。以下のコードではやりたいことが示されている。

#include <streambuf>  // std::streambuf 用
#include <ostream>    // 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 ) // これは認められていない。
                                          // std::ostream より前に初期化することは出来ない。
        {}
    //...
};

メンバによる基本クラスの初期化(base-from-member)イディオムによる解法は以下の通りである。

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

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

struct fdostream_pbase
{
    fdoutbuf sbuffer;

    explicit fdostream_pbase( int fd )
        : sbuffer( fd )
        {}
};

class fdostream
    : private fdostream_pbase
    , public std::ostream
{
    typedef fdostream_pbase  pbase_type;
    typedef std::ostream     base_type;

public:
    explicit fdostream( int fd )
        : pbase_type( fd ), base_type( &sbuffer )
        {}
    //...
};

既知の利用 編集

関連するイディオム 編集

References 編集

  1. ^ Boost Utility http://www.boost.org/libs/utility/base_from_member.html