有些时候设计类时,其父类的初始化需要使用当前类的数据成员,先看下面的场景:
#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 )
{}
//...
};
C++的初始化顺序要求先初始化父类,先调用父类的构造函数,而调用父类构造函数时,buf当时并没有构造。因此类的行为就很难确定。
R. Samuel Klatchko提出了一个方式来解决初始化顺序的问题。基类构造函数的调用依赖基类的继承顺序,将成员移动到基类,然后设置好继承顺序。
#include <streambuf> // for std::streambuf
#include <ostream> // for 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 )
{}
//...
};
上述方式可以使用模板的方式来实现,因此就出现了boost中的base_from_member方式。
参考:
http://www.boost.org/doc/libs/1_46_1/libs/utility/base_from_member.html