2016-02-02 4 views
3

Je pensais au mécanisme de polymorphisme en C++ et je ne peux pas comprendre une chose. Ici, j'ai très simple morceau de code avec une classe:Polymorphisme en C++ idée de vtable (liaison dynamique)

#include <iostream> 

using namespace std; 

class A 
{ 
public: 
    int x; 
    void fun1(); 
    double fun2(int, char*); 
    void fun3(double, float[]); 
}; 

int main() 
{ 
    cout << sizeof(A) << endl; 
return 0; 
} 

Sur la console, il y aura la taille de l'objet imprimé int (x) - il est évident. Si je modife ma classe en ajoutant un mot-clé virtuel, la taille changera car les compilateurs ajoutent un pointeur au tableau (vtable) des fonctions virtuelles. Mais comment est-il possible que la taille de ma classe ne change pas en écrivant des déclarations de nouvelles méthodes virtuelles de signatures complètement différentes? Je veux dire que:

void (*(tab[100]))(int, double, char*); 

Il est une définition de tableau qui est obligé de a adresses de fonctions avec la signature:

void fun(int, double, char*); 

Et que ce type de fonctions peuvent être ajoutées à ce tableau, alors pourquoi peu importe de type de classe de méthode virtuelle contient un seul pointeur vers un tableau virtuel? Où ai-je fait une erreur dans ma logique?

+5

Pour clarifier: La vtable ne fait pas partie de chaque instance de classe; c'est comme un membre statique et n'existe qu'une seule fois. –

Répondre

1

première chose tout d'abord - la norme ne dit pas rien sur les tables virtuelles. il ne parle que de fonctions virtuelles et de polymorphisme. chaque compilateur est autorisé à implémenter cette fonctionnalité de quelque façon qu'il aime.

Les tables virtuelles ne sont que l'implémentation courante de la fonction virtuelle, elle n'est pas mendatoire, et l'implémentation est différente dans chaque compilateur.

enfin, sur mon Visual Studio 2015, ceci:

class A1 { 
    int x; 
    void doIT(){} 
}; 

class A2 { 
    int x; 
    virtual void doIT(){} 
}; 

constexpr int size = sizeof(A1); 
constexpr int size2 = sizeof(A2); 

fait size 4 octets, mais size2 12 octets, ce qui brise vos hypothèses.
nouveau, GCC, Clang et même C++/CLI peuvent avoir un comportement différent, et donnent une taille différente.

2

Il pourrait être useful:

Le tableau virtuel est en fait assez simple, mais il est un peu complexe à décrire en mots. Tout d'abord, chaque classe qui utilise des fonctions virtuelles (ou est dérivée d'une classe qui utilise des fonctions virtuelles) reçoit sa propre table virtuelle. Cette table est simplement un tableau statique que le compilateur met en place au moment de la compilation. Une table virtuelle contient une entrée pour chaque fonction virtuelle pouvant être appelée par les objets de la classe. Chaque entrée dans ce tableau est tout simplement un pointeur de fonction qui pointe vers la fonction la plus dérivée accessible par cette classe