Идиоме base-from-member иногда требуется защищенное наследование.
Проблема, которую решает идиома, заключается в следующем: иногда вам нужно инициализировать базовый класс с членом производного класса, как в
struct foo
{
virtual ~foo() {}
protected:
foo(std::ostream& os)
{
os << "Hello !\n";
}
};
struct bar : foo
{
bar(const char* filename)
: foo(file), file(filename) // Bad, file is used uninitialized
{}
private:
std::fstream file;
};
Но file
создается после foo
, и поэтому ostream
, переданный foo::foo
, недействителен.
Вы решаете это с помощьювспомогательный класс и частное наследование:
struct bar_base
{
std::fstream file;
protected:
bar_base(const char* filename)
: file(filename)
{}
~bar_base() {}
};
struct bar : private bar_base, public foo
{
bar(const char* filename)
: bar_base(filename), foo(file)
{}
};
Теперь bar_base
создан до foo
, и ostream
, переданный в foo::foo
, действителен.
Если вы хотите file
чтобы стать защищенным членом bar
, вы должны использовать защищенное наследование:
struct bar : protected bar_base, public foo { ... }