7
votes

Pourquoi la taille d'une classe dérivée comprend-elle les membres privés de la classe de base?

J'ai le code suivant: xxx

lorsque je vérifie Tailleof (B) , il semble être Tailleof (Base) + Tailleof (dérivé ) . Cependant, ma compréhension de l'héritage est que les membres d'une classe de base ne sont pas hérités. Pourquoi alors sont-ils inclus dans le résultat de tailleof (b) ?


7 Réponses :


8
votes

Toutes les variables des membres sont héritées. le Public Protected Public Les modificateurs ne modifient que ceux qui ont accès à ces variables


0 commentaires

0
votes

Spécificateurs d'accès (public / privé / protégé) n'affectez pas de "taille de l'objet" héritée de toute façon.


3 commentaires

Ils font. Ils contrôlent quels membres de la classe seront visibles dans la classe de convivialité.


@iammilind: ils affectent aussi la taille. En raison d'une règle arcanique qui stipule qu'elles affectent la disposition de la classe, la modification d'un spécificateur peut changer la taille de la classe finale ...


Le droit de Matthieu - 11.1-2 et 9.2-12 - Rappelez-vous vaguement des discussions sur cela permettent à chaque vérification du décalage du membre pour indiquer également le niveau de protection (c'est-à-dire (quelque_class_member.offset> = first_private_offset) / * C'est privé * /). Il aurait également pu être une tentative visant à faciliter l'utilisation d'un mécanisme de sécurité réelle ou postulé de temps d'exécution (par exemple avec du matériel permettant un contrôle d'accès à la mémoire à grain fin, verrouiller / déverrouiller des fonctions de membre privé appelées / retour). Quoi qu'il en soit, les règles d'alignement signifient que l'ordre peut affecter l'efficacité du rembourrage.



3
votes

Il est hérité - l'objet de classe dérivé le contiendra, mais il est impossible d'accéder aux fonctions des membres de la classe dérivée.


1 commentaires

Hey..Merci beaucoup..so La classe dérivée hérite tout, mais les fonctions de membres publics de la classe dérivée ne peuvent pas accéder aux membres privés de la classe de base RI8!



6
votes

Vous avez mal compris ce que privé fait. Dans votre code de code, il empêche tout simplement des non-membres et des non-amis de A d'accéder à i . C'est juste un modificateur contrôle d'accès . Les instances de B auront des membres de données de A , même si B n'aura pas (Direct) y accéder.

Une analogie Cela montre que cela fait en fait un sens: xxx

même si cerveau est privé dans la classe Human , < Code> Stackoverflowuserinsilico Ceci est nécessaire, sinon la fonction useCogogitiveurs () ne fonctionnera pas même si Stackoverflowuserinsilico hérite de la méthode de humain

Bien entendu, que les sous-classes de humain profitent réellement de la méthode useCogogitiveurs () la méthode donnée par la classe humain est une question totalement différente .


1 commentaires

@David: C'est parce que l'argument est faux. L'argument correct est le suivant: X est un humain, les humains ont des cerveaux, donc x a un cerveau qui est parfaitement raisonnable.



0
votes

Je ne sais pas quelle langue c'est, mais lorsque vous héritez que l'objet original existe toujours. C'est pourquoi vous pouvez toujours appeler base.Method ()


0 commentaires

3
votes

Cela a déjà été répondu dans quelques autres réponses: les spécificateurs d'accès restreignent accès em>, mais les attributs membres de la classe sont toujours hérités.

Je voulais juste fournir une justification, comme je généralement apprendre mieux quand je vois les raisons de cela. Fondamentalement, lorsque vous hériter d'un type, le type dérivé contient em> un sous-observateur du type de base, aussi petit ou important que la base pourrait l'être. La raison de besoin de em> toutes les variables de membre est que l'objet dérivé est em> un objet de base et les fonctions de membre de base peuvent être appelées dessus. Même si le type dérivé ne peut pas accéder à l'attribut membre privé, les méthodes de base que l'on peut appeler sur cet objet pourraient encore y accéder. Les membres doivent donc être présents: P>

class base {
   int x;
public:
   base() : x(0) {}
// ...
   void printout() {
      std::cout << x << std::endl;
   }
};
class derived : public base {
// ... assume that derived does not hide `printout`
};
int main() {
   derived d;
   d.printout();  // this requires access to d.base::x
}


0 commentaires

5
votes

Vous vous méprenez-vous Tailleof ou votre malentendez la mise en page (en mémoire) d'objets C ++.

Pour la raison de la performance (pour éviter le coût de l'indirection), les compilateurs mettront souvent en œuvre une dérivation à l'aide de la composition: xxx

Notez que si privé , B ne peut pas jeter sur a même s'il contient IT.

Le Taille de l'opérateur retournera la taille de B , y compris le remplissage nécessaire (pour la correction d'alignement) le cas échéant.

Si vous voulez en savoir plus, je recommande de tout cœur à l'intérieur du Modèle d'objet C ++ par Stanley A. Lippman . Bien que le compilateur dépend, de nombreux compilateurs utilisent en fait les mêmes principes de base.


8 commentaires

Comment cela serait-il implémenté exactement sans le faire de cette façon? (Visez un coût d'indirection?)


@Billy: Vous pouvez décider que les classes de base sont intégrées via un pointeur (créé par nouveau et supprimé par Supprimer ). Ensuite, la classe de base occuperait toujours 4 ou 8 octets (selon le système). Ce serait un peu mieux abi sage, mais beaucoup plus coûteux.


M.: En fait, vous ne pouvez pas faire ça. S'il est créé comme une variable automatique, il doit exister en stockage automatique. Utiliser quelque chose comme Nouveau le mettrait en stockage dynamique. (De plus, si tout ce que vous avez eu était un pointeur de classe de base, vous n'avez aucun moyen de revenir aux parties dérivées de l'objet - les bases ne connaissent pas leurs dérivés)


@Billy: La variable automatique ne signifie pas pile , cela signifie que la mémoire est gérée pour vous. Bon point WRT obtient de la base à dérivé, mais votre oublie qu'il est déjà résolu pour le héritage virtuel (bien que ce soit plus coûteux).


La plupart des héritages ne sont pas virtuels. Je ne vois pas comment cela résout quoi que ce soit.


@Billy: Je n'ai pas dit cela résolu, je souligne simplement que la norme ne manda pas la représentation de l'objet, il s'agit d'une décision écrivaine du compilateur, et le mécanisme de l'héritage virtuel pourrait également être utilisé pour l'héritage régulier, auquel cas Taille de ne serait pas affecté par la taille de la classe de base. Il n'y a pas de mise en œuvre C ++ que je connaisse de l'OMS qui utilise un tel système gaspillé.


Je pense que cela relève de la catégorie des choses qui ne sont pas techniquement mandatées, mais sont implicites, par la norme, telle que std :: basique_string :: opérateur (supports) renvoyer une référence à un type de caractères contenus dans un tampon contigu . (Ne peut pas utiliser [] ci-dessus parce que la liaison le mange ...)


@Billy: aucune idée, je ne suis toujours pas suffisamment versé dans la normale pour comprendre toutes les règles, de sorte que déduire est assez hors de portée: D