Можно использовать B1
часть this
, потому что она уже инициализирована. §12.6.2 / 5: «прямые базовые классы должны быть инициализированы в порядке объявления, как они появляются в списке базовых спецификаторов (независимо от порядка mem-initializer).»
Список базовых спецификаторов здесь равен class D : public B1, public B2
, а список mem-initializer-list равен D::D() : B1(), B2( … )
.
Я бы сказал, что это имеет "кодовый запах".
РЕДАКТИРОВАТЬ: Теперь я понимаю вашу озабоченность, является ли this
неопределенным вне тела конструктора, который не включает инициализаторы членов. Язык, позволяющий это, скрыт между двумя примерами, и я сначала его пропустил. Пункт 7: «Имена в списке выражений mem-инициализатора оцениваются в области действия конструктора, для которого
задан mem-initializer. "
Если B2
действительно нужно сохранить указатель на B1
, и этот указатель всегда будет указывать внутри самого производного объекта, рассмотрим виртуальное наследование.
class B1 {};
class B2 : virtual B1 {}; // under the hood, B2 has a pointer to B1.
class D : public virtual B1, public B2 {}; // D has a pointer too
// Only the most-derived class (the one actually used for instantiation)
// implements space for and initialization of the B1.