Recently, I've been reading "inside the c++ object model". It says that the padding used in base class should also be copied into the derived class, in case you want to assign the base class to the derived class. Thus, I run a test under a 64-bit computer:
class A {
public:
int valA;
char a;
};
class B : public A {
public:
char b;
};
class C : public B {
public:
char c;
};
int main(){
std::cout << sizeof(A) << " " << sizeof(B) << " " << sizeof(C)
<< std::endl;
C c;
printf("%p\n%p\n%p\n",&c,&c.b,&c.c);
}
Here is the result:
8 12 12
0x7ffd22c5072c
0x7ffd22c50734
0x7ffd22c50735
So why is C the same size of B? Although it seems that B used the 3 byte padding in A.
A base class is also called parent class or superclass. Derived Class: A class that is created from an existing class. The derived class inherits all members and member functions of a base class. The derived class can have more functionality with respect to the Base class and can easily access the Base class.
// As base-class pointer cannot access the derived class variable.
Explanation: A base class pointer can point to a derived class object, but we can only access base class member or virtual functions using the base class pointer because object slicing happens when a derived class object is assigned to a base class object.
Moreover, Object slicing happens when a derived class object is assigned to a base class object, and additional attributes of a derived class object are sliced off to form the base class object.
So why is C the same size of B?
Because trailing padding of B
was reused for C::b
. The padding can be reused because B
is not a POD (plain old data) class (because it is not a standard layout class).
Although it seems that B used the 3 byte padding in A.
The padding of A
cannot be reused for other sub objects of B
, because A
is a standard layout class and is trivially copyable i.e. A
is a POD class.
will the padding of base class be copied into the derived class?
I suppose that you didn't mean to ask about copying, but are rather whether the base class sub object of a derived class will have the same padding as the individual type.
The answer is, as might be deduced from the above: The padding will be same, except the trailing padding may be re-used for other sub objects, unless the base class is a POD, in which case its padding can not be reused.
In the case where the padding may be reused, whether it will be is not specified by the standard, and there are differences between compilers.
Please explain or link to a definition of "standard layout types".
Current standard draft:
[basic.types]
... Scalar types, standard-layout class types ([class.prop]), arrays of such types and cv-qualified versions of these types are collectively called standard-layout types.
[class.prop] (in older versions of the standard, these may be found under [class] directly)
A class S is a standard-layout class if it:
(3.1) has no non-static data members of type non-standard-layout class (or array of such types) or reference,
(3.2) has no virtual functions and no virtual base classes,
(3.3) has the same access control for all non-static data members,
(3.4) has no non-standard-layout base classes,
(3.5) has at most one base class subobject of any given type,
(3.6) has all non-static data members and bit-fields in the class and its base classes first declared in the same class, and
(3.7) has no element of the set M(S) of types as a base class, where for any type X, M(X) is defined as follows.107 [ Note: M(X) is the set of the types of all non-base-class subobjects that may be at a zero offset in X. — end note]
(3.7.1) If X is a non-union class type with no (possibly inherited) non-static data members, the set M(X) is empty.
(3.7.2) If X is a non-union class type with a non-static data member of type X0 that is either of zero size or is the first non-static data member of X (where said member may be an anonymous union), the set M(X) consists of X0 and the elements of M(X0).
(3.7.3) If X is a union type, the set M(X) is the union of all M(Ui) and the set containing all Ui, where each Ui is the type of the ith non-static data member of X.
(3.7.4) If X is an array type with element type Xe, the set M(X) consists of Xe and the elements of M(Xe).
(3.7.5) If X is a non-class, non-array type, the set M(X) is empty.
Item (3.6) applies in this case. Some members of B are not first declared in B. In particular, B::A::valA, and B::A::a are declared first in A. A friendlier way to describe the rule is: The class must have either no direct members, or none of its ancestors must have members. In this case both the base and the derived class have members, so it is not standard layout.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With