2009-08-14 7 views
16

En C++, quel est le surcoût (memory/cpu) associé à l'héritage d'une classe de base qui n'a pas de fonctions virtuelles? Est-ce aussi bon qu'une copie directe + pâte des membres de la classe?Surcharge de l'héritage C++ sans fonctions virtuelles

class a 
{ 
public: 
    void get(); 
protected: 
    int _px; 
} 

class b : public a 
{ 

} 

par rapport à

class a 
{ 
public: 
    void get(); 
protected: 
    int _px; 
} 

class b 
{ 
public: 
    void get(); 
protected: 
    int _px; 

} 
+5

Quel est le point dans l'utilisation de l'héritage (public) si vous n'avez pas de fonctions virtuelles? Vous aurez besoin d'au moins un destructeur virtuel. –

+8

@Neil pourrait être pour la réutilisation de code, en évitant la réinvention de la roue – vehomzzz

+5

Dans ce cas, il devrait utiliser la composition, l'héritage privé ou des fonctions libres. –

Répondre

23

Il pourrait y avoir un être légère surcharge de la mémoire (en raison de padding) lors de l'utilisation d'héritage par rapport à la copie et au-delà, tenez compte des définitions de classe suivantes:

struct A 
{ 
    int i; 
    char c1; 
}; 

struct B1 : A 
{ 
    char c2; 
}; 


struct B2 
{ 
    int i; 
    char c1; 
    char c2; 
}; 

sizeof (B1) seront probablement 12, tandis que sizeof (B2) pourrait juste être 8. C'est parce que la classe de base A est rembourrée séparément à 8 octets, puis B1 est rembourré de nouveau à 12 octets.

+0

Ah belle observation. – jameszhao00

+0

Toutes les autres réponses sont valides, mais c'est quelque chose que je ne savais pas/penser avant. – jameszhao00

1

Pas vraiment, il n'a augmenté que la mémoire de la classe de base. Vous pouvez en lire plus dans here en C++ FAQ

+0

Je suis conscient qu'il y a un coût de la table de fonctions dès que des fonctions virtuelles sont introduites. Je me demande comment le compilateur C++ traite l'héritage sans polymorphisme. – jameszhao00

+0

pour un, il n'alloue pas de mémoire pour vtable, ne crée pas de vpointer dans la classe de base, donc le compilateur et l'exécution prennent moins de temps qu'avec la fonction/dtors virtuelle. Qu'est-ce que vous essayez d'accomplir? – vehomzzz

14

La compilation prendra un peu plus de temps et il n'y aura pas de temps d'exécution supplémentaire. Du point de vue de l'optimiseur, les méthodes non virtuelles sont les mêmes que les procédures - elles peuvent être appelées en utilisant uniquement leur adresse mémoire, sans surcharge d'une table de méthodes virtuelle.

+0

Pourquoi cela prendrait plus de temps à compiler? juste curieux. Je pensais que les compilateurs étaient assez intelligents ces jours-ci :) – vehomzzz

+6

L'augmentation du temps ne sera que de quelques millisecondes, puisque le compilateur devra construire l'arbre d'héritage. Cela ne vaut pas la peine de s'en soucier. –

+0

Ne voulez-vous pas dire "la même chose que les méthodes non héritées"? – einpoklum

3

Si vous oubliez l'héritage virtuel, avoir une classe de base est équivalente, en termes de mémoire et de performances, à un membre de la même classe. Excepté que cela peut parfois être encore mieux (par exemple une classe vide a une taille d'au moins un, mais avoir une classe de base vide peut souvent ne pas avoir de frais généraux).

2

Si vous avez un pointeur de type Base * qui pointe vers un objet de type Derived *, vous avez probablement besoin d'un destructeur virtuel et votre prémisse d'origine ne s'applique plus. Si la classe dérivée a un destructeur vide, et qu'il n'y a pas de membres ou qu'ils sont tous des types POD, vous pouvez vous en passer sans un destructeur virtuel, mais il est généralement préférable de le jouer en toute sécurité et de le rendre virtuel dès le départ.

Le compilateur génère un appel direct au code implémentant chaque fonction membre non virtuelle, il n'y a donc pas de surcharge.

Questions connexes