2010-01-31 4 views
19

Je lis beaucoup de gens qui écrivent "une table virtuelle existe pour une classe qui a une fonction virtuelle déclarée dedans".Table virtuelle C++

Ma question est, est-ce qu'un vtable existe seulement pour une classe qui a une fonction virtuelle ou existe-t-il aussi pour les classes dérivées de cette classe.

par exemple

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(); 

Question: Y avait-il pas eu vtable pour la classe dérivée, la sortie n'aurait pas été « impression dérivée ». Donc, IMO il existe un vtable pour toute classe qui a une fonction virtuelle déclarée et aussi dans les classes héritant de cette classe. Est-ce correct ?

+2

Pour terminer l'expérience, créez la classe derived2 qui hérite de derived et remplace également print. Appelez print sur une telle instance via un pointeur vers la base ... – VoidPointer

+2

En savoir plus sur le Vtable @ ci-dessous Lien: http://www.learncpp.com/cpp-tutorial/125-the-virtual-table/ –

Répondre

19

En ce qui concerne uniquement les fonctionnalités spécifiques à la fonction virtuelle est considérée, dans une approche traditionnelle de VTABLE classe dérivée de la mise en œuvre aurait besoin d'une version distincte de vtable si et seulement si cette classe dérivée remplace au moins une fonction virtuelle. Dans votre exemple, Derived remplace la fonction virtuelle print. Puisque Derived a sa propre version de print, l'entrée correspondante dans Derived vtable est différente de celle de Base vtable. Cela nécessiterait normalement une vtable distincte pour Derived.

Si Derived ne l'emportait pas sur quoi que ce soit, formellement, il serait encore une classe polymorphique séparée, mais pour rendre ses fonctions virtuelles fonctionnent correctement, nous aurions pu simplement réutilisé Base vtable pour Derived aussi bien. Donc, techniquement, il n'y aurait pas besoin d'un vtable séparé pour Derived. Cependant, dans les implémentations pratiques, la structure de données que nous appelons généralement «vtable» contient souvent également des informations spécifiques à la classe. Ces informations supplémentaires sont si spécifiques à la classe que la plupart du temps, il devient impossible de partager des vtables entre différentes classes de la hiérarchie, même si elles utilisent le même ensemble de fonctions virtuelles. Par exemple, dans certaines implémentations, le pointeur vtable stocké dans chaque objet polymorphe pointe vers une structure de données qui stocke également les «informations RTTI» sur la classe.Pour cette raison, dans la plupart des implémentations pratiques (sinon toutes), chaque classe polymorphe obtient sa propre vtable, même si les pointeurs de fonction virtuelle stockés dans ces tables sont identiques.

+1

@AndreyT: Connaissez-vous une page Web qui explique les concepts liés à 'vtable' pour C++ dans un bon sens pour un débutant? J'essaie de comprendre pourquoi un vtable est nécessaire et comment exactement il est mis en œuvre. – Lazer

+0

Les détails de mise en œuvre de @Lazer ne sont pas spécifiés. La table est nécessaire pour que le système sache quelle version d'une fonction polymorphe appeler (ceci ne peut pas être déterminé au moment de la compilation, considérer une opération sur un pointeur de classe de base - l'opération pourrait être différente si le pointeur pointe vers une instance de classe dérivée ou instance de classe de base). Voir https://en.wikipedia.org/wiki/Virtual_method_table – RJFalconer

2

Oui, c'est vrai. Une classe hérite de tous les membres de données de sa classe de base, y compris vtable. Cependant, les entrées vtable sont ajustées en conséquence (par exemple, si la classe remplace une méthode virtuelle de classe de base, l'entrée correspondante dans vtable doit pointer vers sa propre implémentation). Mais gardez à l'esprit que le concept de «vtable» est une pratique courante utilisée par tous les compilateurs, mais il n'est pas obligatoire ni standardisé.

+0

Le vtable est pas un membre ou quelque chose comme un membre. Voulez-vous dire vptr? – curiousguy

3

Oui, votre compréhension est correcte. Toute classe qui a une base avec des fonctions virtuelles a un vtable.

3

Oui, c'est vrai. En fait, la défintion de base donnée:

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

est tout à fait équivalent à:

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

... parce que vous imprimez déjà défini comme virtuel dans la base.

Je souhaite que le compilateur imposerait que ...

Questions connexes