2009-08-14 4 views
16

In C++, qual è l'overhead (memoria/CPU) associato all'ereditarietà di una classe base che non ha funzioni virtuali? È buono come copia e incolla di membri della classe?Sovraccarico di ereditarietà C++ senza funzioni virtuali

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

class b : public a 
{ 

} 

rispetto al

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

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

} 
+5

Qual è il punto in cui si utilizza l'ereditarietà (pubblica) se non si dispone di funzioni virtuali? Avrai bisogno almeno di un distruttore virtuale. –

+8

@Neil potrebbe essere riutilizzato per il codice, evitando la reinvenzione della ruota – vehomzzz

+5

In tal caso, egli dovrebbe utilizzare la composizione, l'ereditarietà privata o le funzioni libere. –

risposta

23

Ci potrebbe un essere leggero sovraccarico della memoria (a causa di imbottitura) quando si utilizza l'ereditarietà rispetto a copiare e incollare, considerare i seguenti definizioni di classe:

struct A 
{ 
    int i; 
    char c1; 
}; 

struct B1 : A 
{ 
    char c2; 
}; 


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

sizeof (B1) sarà probabilmente il 12, mentre sizeof (B2) potrebbe essere solo 8. Questo perché la classe base A viene riempita separatamente a 8 byte e poi B1 viene riempito nuovamente a 12 byte.

+0

Ah bella osservazione. – jameszhao00

+0

Tutte le altre risposte sono valide, ma questa è una cosa che non sapevo/pensavo prima. – jameszhao00

1

Non proprio, è aumentato solo la memoria dalla classe base. Puoi leggere di più in here in C++ FAQ

+0

Sono consapevole che esiste un costo per la tabella delle funzioni non appena vengono introdotte le funzioni virtuali. Mi chiedo come il compilatore C++ elabora l'ereditarietà senza polimorfismo. – jameszhao00

+0

per uno, non alloca memoria per vtable, non crea un vpointer nella classe base, quindi sia il compilatore che il runtime richiedono meno rispetto a funzione/dvd virtuali. cosa stai cercando di realizzare? – vehomzzz

14

Ci vorrà molto più tempo per compilare, e non ci sarà nessun sovraccarico di runtime aggiuntivo. Dal punto di vista dell'ottimizzatore, i metodi non virtuali sono gli stessi delle procedure: possono essere chiamati utilizzando solo il loro indirizzo di memoria, senza sovraccarico da una tabella dei metodi virtuale.

+0

Perché impiegare più tempo per compilare? solo curioso. Pensavo che i compilatori fossero abbastanza intelligenti in questi giorni :) – vehomzzz

+6

Il tempo incrementato sarà di pochi millisecondi, poiché il compilatore dovrà costruire l'albero di ereditarietà. Non vale la pena prendersene cura. –

+0

Non intendi "uguale a metodi non ereditari"? – einpoklum

3

Se si dimentica l'ereditarietà virtuale, avere una classe base è equivalente, memoria e prestazioni saggia, a un membro della stessa classe. Tranne che a volte può essere anche migliore (ad esempio una classe vuota ha una dimensione di almeno una, ma avere una classe base vuota può spesso non avere un sovraccarico).

2

Se si dispone di un puntatore di tipo Base * che punta a un oggetto di tipo Derivato *, è probabilmente necessario un distruttore virtuale e la premessa originale non è più valida. Se la classe derivata ha un distruttore vuoto e non ha membri o sono tutti tipi POD, puoi andare via senza un distruttore virtuale, ma di solito è meglio giocare sul sicuro e renderlo virtuale fin dall'inizio.

Il compilatore genererà una chiamata diretta al codice che implementa ogni funzione membro non virtuale, quindi non c'è nessun sovraccarico.