2010-01-31 24 views
19

Ho letto molte persone che scrivono "esiste un tavolo virtuale per una classe che ha una funzione virtuale dichiarata".Virtual Table C++

La mia domanda è, esiste un vtable solo per una classe che ha una funzione virtuale o esiste anche per le classi derivate da quella classe.

es

class Base{ 
    public: 
     virtual void print(){cout<<"Base Print\n";} 
}; 
class Derived:public Base{ 
    public: 
     void print(){cout<<"Derived print\n";} 
}; 

//From main.cpp 
Base* b = new Derived; 
b->print(); 

Domanda: Se non ci fosse stato alcun vtable per la classe derivata "print derivata" allora l'uscita non sarebbe stato. Quindi IMO esiste un vtable per qualsiasi classe che ha dichiarato la funzione virtuale e anche nelle classi che ereditano da quella classe. È corretto ?

+2

Per completare l'esperimento, creare la classe derivata2 che eredita da derivata e sovrascrive anche la stampa. Chiama stampa su tale istanza tramite un puntatore alla base ... – VoidPointer

+2

Ulteriori informazioni sulla Vtable @ sotto Link: http://www.learncpp.com/cpp-tutorial/125-the-virtual-table/ –

risposta

19

Per quanto riguarda solo la funzionalità virtual-funzione-specifica è considerata, in un approccio tradizionale alla vtable implementazione della classe derivata avrebbe bisogno di una versione separata di vtable se e solo se la classe derivata sostituisce almeno una funzione virtuale. Nel tuo esempio, Derived sostituisce la funzione virtuale print. Poiché Derived ha una propria versione di print, la voce corrispondente nel vtable Derived è diversa da quella in vtable Base. Ciò richiederebbe normalmente un vtable separato per Derived.

Se Derived non ha sovrascrivono nulla, formalmente ancora sarebbe una classe polimorfica separato, ma al fine di rendere le sue funzioni virtuali funzionano correttamente avremmo potuto semplicemente riutilizzato Base vtable per Derived pure. Quindi, tecnicamente non ci sarebbe bisogno di un vtable separato per Derived.

Tuttavia, nelle implementazioni pratiche, la struttura dati che di solito chiamiamo "vtable", spesso contiene anche informazioni aggiuntive specifiche della classe. Queste informazioni extra sono così specifiche della classe che la maggior parte delle volte diventa impossibile condividere vtables tra diverse classi nella gerarchia, anche se usano lo stesso insieme di funzioni virtuali. Ad esempio, in alcune implementazioni il puntatore vtable memorizzato in ogni oggetto polimorfico punta alla struttura dati che memorizza anche le cosiddette "informazioni RTTI" sulla classe.Per questo motivo, nella maggior parte (se non tutte) le implementazioni pratiche ogni classe polimorfica ottiene il proprio vtable, anche se i puntatori di funzione virtuale memorizzati in quei tavoli capita di essere gli stessi.

+1

@AndreyT: conosci qualche pagina web che spiega i concetti relativi a 'vtable' per C++ in un buon modo per un principiante? Sto cercando di capire perché è necessario un vtable e come viene implementato esattamente. – Lazer

+0

I dettagli di implementazione di @Lazer non sono specificati. La tabella è richiesta in modo che in fase di esecuzione il sistema sappia quale versione di una funzione polimorfica chiamare (questo non può essere determinato in fase di compilazione, si consideri un'operazione su un puntatore di classe base - l'operazione potrebbe essere diversa se il puntatore punta a un'istanza di classe derivata o istanza di classe base). Vedi https://en.wikipedia.org/wiki/Virtual_method_table – RJFalconer

2

Sì, è vero. Una classe eredita tutti i membri dati dalla sua classe base, incluso il vtable. Tuttavia, le voci vtable vengono regolate di conseguenza (ad esempio se la classe sostituisce un metodo virtuale di classe base, la voce corrispondente nel vtable deve puntare alla propria implementazione).

Ma tieni presente che il concetto di "vtable" è una pratica comune utilizzata da ogni compilatore per vizio, ma non è obbligatoria né standardizzata.

+0

Il vtable è non un membro o qualcosa come un membro. Intendi vptr? – curiousguy

3

Sì, la vostra comprensione è corretta. Qualsiasi classe che abbia una base con qualsiasi funzione virtuale ha un vtable.

3

Sì, è vero. In realtà, defintion data della base:

class derived:public base{ 
public: 
void print(){cout<<"derived print\n";} 
}; 

è del tutto equivalente a:

class derived:public base{ 
public: 
virtual void print(){cout<<"derived print\n";} 
}; 

... perché già definito di stampa come virtuale in base.

avrei voluto il compilatore imporrebbe che ...

Problemi correlati