Pourquoi sizeof (BaseClass) == sizeof (DerivedClass) bien que j’ajoute un membre

À partir du code ci-dessous sizeof(Base) == 24 et sizeof(Derived) == 24 .

Pourquoi leurs tailles sont-elles égales?

Dans la classe de Base , nous avons 3 membres et dans la classe Derived , nous avons un autre membre.

 class Base { private: double d; protected: long l; public: int i; }; class Derived : public Base { private: float f; }; 

Il se trouve que votre classe Base a une exigence d’alignement de 8 octets, mais que son dernier membre a la taille 4. Cela conduit à une zone de remplissage vide ajoutée à la fin de la disposition de la mémoire de Base . Ce remplissage supplémentaire joue son rôle lorsque vous instanciez des objects de classe Base par eux-mêmes, appelés objects les plus dérivés .

 Base b; // <- a most-derived object Base a[10]; // <- an array of most-derived objects 

Cependant, lorsque vous "intégrez" Base tant que classe de base dans la classe Derived , vous n'avez pas besoin de ce remplissage supplémentaire à la fin du sous-object Base Embedded.

 Derived d; // <- object `d` contains an embedded sub-object of type `Base` 

Un compilateur intelligent tente de réutiliser cette zone en plaçant le champ supplémentaire de la classe Derived dans la zone de présentation utilisée pour le remplissage dans Base . Dans votre cas, le champ supplémentaire Derived::f a la même taille de 4 octets, c’est-à-dire qu’il s’insère parfaitement. Le résultat final est que la taille totale de la classe n'augmente pas.

Un effet très similaire (dans la nature) est appelé "optimisation de la base vide". En C ++, sizeof pour tout type est garanti supérieur à 0, ce qui signifie que sizeof d'une classe vide est toujours supérieur à zéro. Cependant, lorsque vous dérivez une autre classe d'une classe de base vide, vous pouvez observer que la classe de base consortingbue exactement à 0 octet à la taille de la classe dérivée. Par exemple

 struct A {}; struct B {}; struct C {}; struct D {}; struct F : A, B, C, D { int i; } int main() { std::cout << sizeof(A) << std::endl << sizeof(B) << std::endl << sizeof(C) << std::endl << sizeof(D) << std::endl; std::cout << sizeof(F) << std::endl; } 

Même si sizeof de chaque classe de base est supérieur à zéro, sizeof(F) évaluera généralement à sizeof(int) , comme si les sous-objects de classe de base n'existaient pas du tout.

En d’autres termes, comme le montrent ces exemples, les sous-objects de classe de base suivent des règles sensiblement plus souples en ce qui concerne leur disposition en mémoire que les objects les plus dérivés. Ces règles assouplies peuvent facilement conduire à des situations où sizeof de la classe de base ne consortingbuera que partiellement à sizeof de la classe dérivée.

Parce que vous avez sizeof (double) == sizeof (long) == 8 et cela signifie souvent que alignof (double) est égal à 8 aussi. Cela signifie que Base doit être aligné sur la taille sur une limite de 8 octets au cas où il serait stocké dans un tableau, et qu’il génèrerait un remplissage de 4 octets à la fin.

Utilisez pahole pour le comprendre:

 class Base { private: double d; /* 0 8 */ protected: long int l; /* 8 8 */ int i; /* 16 4 */ /* size: 24, cachelines: 1, members: 3 */ /* padding: 4 */ /* last cacheline: 24 bytes */ }; class Derived : public Base { public: /* class Base ; */ /* 0 24 */ /* XXX last struct has 4 bytes of padding */ private: /* Bitfield combined with next fields */ float f; /* 20 4 */ /* size: 24, cachelines: 1, members: 2 */ /* paddings: 1, sum paddings: 4 */ /* last cacheline: 24 bytes */ }; 

Rembourrage dû aux besoins d’alignement:

Bien que le compilateur (ou l’interpréteur) atsortingbue normalement des éléments de données individuels sur des limites alignées, les structures de données ont souvent des membres avec des exigences d’alignement différentes. Pour maintenir un alignement correct, le traducteur insère normalement des membres de données non nommés supplémentaires afin que chaque membre soit correctement aligné. De plus, la structure de données dans son ensemble peut être complétée par un membre final sans nom. Cela permet à chaque membre d’un tableau de structures d’être correctement aligné.

Plus sur ceci ici:
http://en.wikipedia.org/wiki/Data_structure_alignment#Data_structure_padding