Disposition de la table virtuelle C ++ de MI (inheritance multiple)

Regardez le code C ++ suivant

class Base1 { public: Base1(); virtual ~Base1(); virtual void speakClearly(); virtual Base1 *clone() const; protected: float data_Base1; }; class Base2 { public: Base2(); virtual ~Base2(); virtual void mumble(); virtual Base2 *clone() const; protected: float data_Base2; }; class Derived : public Base1, public Base2 { public: Derived(); virtual ~Derived(); virtual Derived *clone() const; protected: float data_Derived; }; 

Le 《Intérieur du modèle d’object C ++》 4.2 indique que la disposition de la table virtuelle des classes Base1, Base2 et Derived est la suivante: entrez la description de l'image ici

entrez la description de l'image ici

Ma question est :

La table virtuelle du sous-object Base1 de la classe Derived contient Base2::mumble mumble .Why? Je sais que la classe Derived a partagé cette table virtuelle avec Base1. Je pense donc que la fonction de Base2 ne devrait pas apparaître ici. Quelqu’un pourrait-il me dire pourquoi? THX.

Eh bien, tout d’abord, je rappellerai à tous que la conception de la solution pour implémenter le polymorphism est une décision ABI n’appartenant pas à la norme. Par exemple, MSVC et Itanium ABI (suivis de gcc, clang, icc, …) ont différentes manières de mettre en œuvre cela.

Cela dit, je pense qu’il s’agit d’une optimisation de la recherche.

Chaque fois que vous avez un object Derived (ou l’un de ses descendants) et recherchez le membre mumble , vous n’avez pas besoin de rechercher le sous-object Base2 mais vous pouvez agir directement à partir du sous-object Base1 (dont l’adresse coïncide avec le sous-object Derived , aucune arithmétique n’est donc nécessaire. ).

Au moment de l’exécution lorsque vous obtenez:

  Base2 b2; Base1* b1_ptr = (Base1*)&b2; b1_ptr->mumble(); // will call Base2::mumble(), this is the reason. 

Ensuite, Base2 :: mumble () doit être appelé! Veillez à ce que mumble () soit la SEULE méthode virtuelle surchargée dans la hiérarchie. (Même, vous pouvez penser que clone () est aussi redéfini, mais que le type obtenu est différent selon les classes, il s’agit d’une autre signature).