The answer depends on the language version, because this has changed from C++03 to C++11.
In C++03, the rule was:
Members within the same access control block (that is, from one of public
, protected
, private
keywords to the next one from that set) are to be allocated in order of declaration within class, not necessarily contiguously.
In C++11, the rule was changed to this:
Members with the same access control level (public, protected, private) are to be allocated in order of declaration within class, not necessarily contiguously.
So in C++03, you could guarantee this (I use @
to mean the offset of a member within the class):
@m_ac < @m_scp
@m_i1 < @m_i2 < @m_b1 < @m_b2
In C++11, you have a few more guarantees:
@m_ac < @m_scp
@m_sc < @m_i1 < @m_i2 < @m_b1 < @m_b2
@m_name < @m_b3
In both versions, the compiler can re-order the members in different chains as it sees fit, and it can even interleave the chains.
Note that there is one more mechanism which can enter into the picture: standard-layout classes.
A class is standard-layout if it has no virtuals, if all its non-static data members have the same access control, it has no base classes or non-static data members of non-standard-layout type or reference type, and if it has at most one class with any non-static data members in its inheritance chain (i.e. it cannot both define its own non-static data members and inherit some from a base class).
If a class is standard-layout, there is an additional guarantee that the address of its first non-static data member is identical to that of the class object itself (which just means that padding cannot be present at the beginning of the class layout).
Note that the conditions on being standard-layout, along with practical compilers not making pessimising choices, effectively mean that in a standard-layout class, members will be arranged contiguously in order of declaration (with padding for alignment interspersed as necessary).
protected
, avoid naked pointers. – Mooring