It's OK to use the B1
part of this
because it is already initialized. §12.6.2/5: "direct base classes shall be initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers)."
The base-specifier-list here is is class D : public B1, public B2
, and the mem-initializer-list is D::D() : B1(), B2( … )
.
I would say that this has "code smell," though.
EDIT: Now I understand your concern, whether this
is undefined outside the body of the constructor, which doesn't include the member initializers. The language allowing this is buried between two examples and I missed it at first. Paragraph 7: "Names in the expression-list of a mem-initializer are evaluated in the scope of the constructor for which the
mem-initializer is specified."
If B2
actually needs to retain a pointer to a B1
, and that pointer will always point inside the most-derived object, consider virtual inheritance.
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.