51 votes

Le C ++ est-il autorisé à augmenter la taille de la classe dérivée s'il n'y a pas de nouvelle variable membre comparée à la classe de base?

Supposons que j'ai une classe de base avec des variables membres et aucune fonction virtuelle:

 class Base {
   int member;
};
 

et une classe dérivée qui dérive de manière non virtuelle de Base et n'a pas de nouvelles variables de membre ni encore aucune fonction virtuelle:

 class Derived : Base {
};
 

Évidemment, sizeof(Derived) ne peut pas être inférieur à sizeof(Base) .

Est-il nécessaire que sizeof(Derived) soit égal à sizeof(Base) ?

18voto

Tristan Brindle Points 5234

À partir 5.3.2 [expr.sizeof]

Lorsqu'il est appliqué à une classe, le résultat [de sizeof] est le nombre d'octets dans un objet de cette classe, y compris tout remplissage requis pour le placement des objets de ce type dans un tableau. La taille de la plupart de la classe dérivée doit être supérieur à zéro (1.8).

De 1,8 [intro.objet]

Sauf si c'est un peu de champ (9.6), un dérivé de l'objet doit avoir une taille non nulle et doit occuper un ou plusieurs octets de stockage. Classe de Base des sous-objets peuvent avoir la taille zéro. Un objet de type POD (3.9) s'occupent d'octets contigus de stockage.

et une remarque:

La taille réelle d'une classe de base sous-objet peut être inférieur au résultat de l'application de sizeof à la sous-objet, en raison de virtuel les classes de base et moins stricte rembourrage exigences sur la classe de base des sous-objets.

Mettre ces ensemble et je pense que ce qu'il vous dit, c'est que vous n'avez aucune garantie de quelque sorte que ce sizeof peut vous dire, autre que le résultat sera plus grand que zéro. En fait, il ne semblent même pas garantir que sizeof(Derived) >= sizeof(Base)!

13voto

Kerrek SB Points 194696

Il n'y a pas une telle exigence.

La seule partie de la langue, je pense que chaque objet, qu'il soit complet ou non, et si la plupart des dérivés ou non, a une identité, qui est donné par la paire de son adresse et de son type. Cf. C++11 1.8/6:

Deux objets qui ne sont pas des bits de champs peuvent avoir la même adresse si l'on est un sous-objet de l'autre, ou si au moins un est une classe de base sous-objet de la taille de zéro et ils sont de types différents; en cas contraire, ils ont des adresses différentes.

La plupart des dérivés de l'objet et la base de sous-objet de votre exemple, doit avoir des identités distinctes.

Il serait certainement judicieux, pour un compilateur de donner à la fois Base et Derived une taille de 1, mais ce n'est pas obligatoire. Il serait acceptable si l' Base a la taille 1729 et Derived a la taille 2875.

10voto

David M Points 5741

Question intéressante. J'ai un exemple où une classe dérivée, avec un champ supplémentaire est la même taille comme un vide de la classe de base. (Ce devrait être un commentaire mais il est beaucoup trop grand; veuillez accepter l'une des autres réponses, bien que les upvotes sont les bienvenus si c'est intéressant.)

Considérer cette triviale programme en C++:

class A {};

class B : public A {
    int m_iInteger;
};

int _tmain(int argc, _TCHAR* argv[])
{
    printf("A: %d\r\n", sizeof(A));
    printf("B: %d\r\n", sizeof(B));
    printf("int: %d\r\n", sizeof(int));

    return 0;
}

Qu'attendez-vous la sortie, si sizeof(int) 4? Peut-être quelque chose comme:

A: 0
B: 4
int: 4

?

Mon compilateur - Embarcadero C++ Builder 2010 - donne le résultat:

A: 8
B: 8
int: 4

En d'autres termes, l'ajout d'un champ supplémentaire dans la classe dérivée n'a pas la classe dérivée plus grand.

Il y a une certaine idée de la raison pour laquelle dans la rubrique du fichier d'aide sur l' option de compatibilité de longueur Nulle vide de la classe de base.

En général la taille d'une classe est au moins un octet, même si la classe ne pas définir toutes les données membres. Lorsque vous sélectionnez cette option, l' compilateur ignore ce inutilisés octet pour la disposition de la mémoire et le total des taille des classes dérivées; vide classes de base ne consomment pas d'espace dans les classes dérivées. Par Défaut = False

Il semble que la taille d'une classe avec des options de compilation par défaut pour ce compilateur est de 8 octets, pas un, et en fait un changement de ce paramètre pour cet exemple de code n'a aucun effet.

Vous pouvez également trouver cet article sur la base de la taille des classes et au-dessus de l'optimisation intéressante. Il explique pourquoi les classes doivent avoir une taille d'au moins un octet, ce que l'optimisation n', et plonge dans la représentation de fonctions de membre etc trop:

En effet, la norme exige que la taille d'un objet ne doit jamais être égal à zéro; il exige aussi que dans un objet dérivé de données des membres de l' classe de base(es) doivent apparaître avant que l'utilisateur de données déclaré les membres de la la classe dérivée. Cependant, une classe de base sous-objet n'est pas considéré comme un objet complet. Par conséquent, il est possible de supprimer la classe de base sous-objet de l'objet dérivé, sans violer les règles. Dans d'autres termes, l'objet t, le décalage de S et x peuvent se chevaucher...

Veuillez lire l'article pour le contexte de cette citation.

-1voto

Santosh Sahu Points 612
 class Base {
 // int member;            I have just created an empty base class.
};

class Derived : Base {
};
 

Maintenant, le compilateur gcc donnerait "taille> 0" pour les deux objets créés par les classes Base et Derived. Le compilateur gcc fournit simplement la présence de l'adresse des objets à l'utilisateur.

   Note:Derived class would contain base class members, so obviously we can think of 
  sizeof(derived class) greater then sizeof(base class). But this depends on the compiler 
  if it allocates some extra space while defining the derived class. 
 

Mon compilateur gcc actuel a montré que la taille des objets de la base et du dérivé était identique.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X