Maison  >  Article  >  développement back-end  >  Explication détaillée des fonctions de membre virtuel C++ et de la liaison dynamique

Explication détaillée des fonctions de membre virtuel C++ et de la liaison dynamique

hzc
hzcavant
2020-07-01 15:33:062036parcourir

Étude recommandée : "Tutoriel C++"

- Le compilateur utilise la liaison statique pour les méthodes non virtuelles (correspondance au moment de la compilation ), utilisez la liaison dynamique (correspondance d'exécution) pour les méthodes virtuelles.

  • Lorsque les méthodes virtuelles ne sont pas utilisées, le type du pointeur est connu au moment de la compilation, le compilateur peut donc associer la méthode membre à la classe correspondante au moment de la compilation, qui est appelée Liaison statique ;
  • Lors de l'utilisation de méthodes virtuelles, le type d'objet ne peut généralement être déterminé que lorsque le programme est exécuté, de sorte que le code généré par le compilateur associe la fonction membre à la classe correspondante lorsque le programme est exécuté, c'est ce qu'on appelle la liaison dynamique.

La liaison statique est plus efficace que la liaison dynamique.

Comment fonctionnent les fonctions virtuelles.

Fonction virtuelle.

Redéfinir les fonctions membres (changer les signatures des fonctions).

Redéfinissez les fonctions membres surchargées.

Efficacité

Pour que le programme puisse prendre des décisions au moment de l'exécution, une méthode doit être utilisée pour suivre le type d'objet pointé par le pointeur de classe de base ou la référence, ce qui ajoute une surcharge de traitement supplémentaire. Par conséquent, les situations suivantes sont plus adaptées à la liaison statique :

  • La classe ne sera pas utilisée comme classe de base
  • La la classe dérivée ne redéfinit pas la classe de base. Toute méthode de

donc la liaison statique est définie comme choix par défaut pour C++.

Si vous souhaitez redéfinir une méthode de classe de base dans une classe dérivée, définissez-la sur une méthode virtuelle ; sinon, définissez-la sur une méthode non virtuelle.

Comment fonctionnent les fonctions virtuelles

La façon dont le compilateur gère les fonctions virtuelles consiste à ajouter un membre caché à chaque objet. Le membre masqué stocke un pointeur vers le tableau d’adresses de fonction. Ce tableau est appelé table de fonctions virtuelles (vtbl), qui stocke les adresses des fonctions virtuelles déclarées pour les objets de classe.

L'objet de classe dérivé contiendra un pointeur vers une table d'adresses indépendante (c'est-à-dire qu'une nouvelle table est créée). (Augmentation de la surcharge de mémoire)

Lors de l'appel d'une fonction virtuelle, le programme examinera l'adresse vtbl stockée dans l'objet, puis se tournera vers la table d'adresses de fonction correspondante et recherchera l'adresse dans le tableau. (Affecte la vitesse d'exécution)

Bref, utiliser des fonctions virtuelles aura un certain coût en mémoire et en vitesse d'exécution même si les non-fonctions sont légèrement plus efficaces que les fonctions virtuelles, elles n'en ont pas ; avoir une liaison dynamique.

Le constructeur ne peut pas être une fonction virtuelle.

Le destructeur doit être une fonction virtuelle à moins que la classe n'ait pas besoin d'être une classe de base.

Les fonctions amis ne peuvent pas être des fonctions virtuelles, car les amis ne sont pas des membres de la classe et seuls les membres peuvent être des fonctions virtuelles.

Si la classe dérivée ne redéfinit pas la fonction, la version de classe de base de la fonction sera utilisée (en hérite). Si une classe dérivée se trouve dans une chaîne de dérivation, la dernière version de la fonction virtuelle (pointeur ou appel de référence) sera utilisée, sauf si la version de la classe de base est masquée.

La redéfinition masquera la méthode de la classe de base :

class Dwelling
{public:    virtual void showperks(int a) const;
    ...
};class Hovel : public Dwelling
{public:    virtual void showperks() const;
    ...
}

La redéfinition de la fonction dans la classe dérivée (en modifiant la signature du paramètre) la masquera A méthode de classe de base portant le même nom, plutôt que de surcharger une méthode de classe de base.

Hovel trump;
trump.showperks();    // validtrump.showperks(5);    // invalid

Si vous redéfinissez une méthode héritée, assurez-vous qu'elle est exactement la même que le prototype d'origine. Si le type de retour est une référence ou un pointeur de classe de base, il peut être modifié en une référence ou un pointeur vers une classe dérivée (covariance du type de retour : c'est-à-dire que le type de retour est autorisé à changer à mesure que le type de classe change).

Si la déclaration de la classe de base est surchargée, toutes les versions de la classe de base doivent être redéfinies dans la classe dérivée ; si une seule version est définie, les autres versions ne seront pas masquées. pouvoir les utiliser.

class Dwelling
{public:    virtual void showperks(int a) const;    virtual void showperks(double x) const;    virtual void showperks() const;
    ...
};class Hovel : public Dwelling
{    virtual void showperks(int a) const;    virtual void showperks(double x) const;    virtual void showperks() const;
    ...
};

Si aucune modification n'est requise, la nouvelle définition ne peut appeler que la version de la classe de base :

<span class=" cnblogs_code"><span style="color: #0000ff;">void<code> <span class="cnblogs_code"><span style="color: #0000ff;">void</span> Hovel::showperks()<span style="color: #0000ff;">const</span> {Dwelling::showperks();}</span>  Hovel::showperks()const {Dwelling::showperks();}

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer