This all boils down to whether your type is an aggregate or not. With
struct Base {
Base() {}
double foo;
int bar;
};
struct Derived : public Base {
int baz;
};
Base
is not an aggregate because of the constructor. When you remove the constructor, you make Base
an aggregate which, per Adding a default constructor to a base class changes sizeof() a derived type, means gcc won’t “optimize” for space and the derived object won’t use the base’s tail padding.
When you change the code to
class Base {
double foo;
int bar;
};
struct Derived : public Base {
int baz;
};
foo
and bar
are now private (becauses classes have private accessibility by default) which again means Base
is no longer an aggregate as aggregates are not allowed to have private members. This means we are back to how the first case works.