Maison > développement back-end > C++ > Pourquoi l'appel d'une fonction virtuelle dans un constructeur de classe de base entraîne-t-il l'utilisation de l'implémentation de la classe de base ?

Pourquoi l'appel d'une fonction virtuelle dans un constructeur de classe de base entraîne-t-il l'utilisation de l'implémentation de la classe de base ?

Barbara Streisand
Libérer: 2024-12-21 02:03:15
original
860 Les gens l'ont consulté

Why Does Calling a Virtual Function in a Base Class Constructor Result in the Base Class Implementation Being Used?

Remplacer les fonctions virtuelles dans les constructeurs

Considérez l'extrait de code suivant :

#include <iostream>
struct base {
  virtual const int value() const {
    return 0;
  }

  base() { // Default constructor
    std::cout << value() << std::endl;
  }
};

struct derived : public base {
  virtual const int value() const {
    return 1;
  }
};

int main() {
  derived d; // Declares an instance of the derived class
}
Copier après la connexion

Lorsque nous exécutons ce code, il imprime 0 au lieu du 1 attendu. Pourquoi ?

Virtuel Appel de fonction pendant la construction

Lorsqu'un constructeur de classe de base appelle une fonction virtuelle dans le constructeur, la fonction virtuelle est appelée sur l'instance de classe de base plutôt que sur l'instance de classe dérivée. Ceci est le résultat du processus de « maturation » de l'objet pendant la construction.

  • Maturation : Au fur et à mesure qu'un objet est construit, il commence par les constructeurs de la classe de base et progressivement « mûrit » " dans le type de classe dérivé.

Dans notre exemple, le constructeur de base appelle value() lorsque l'objet est partiellement construit. À ce stade, l’objet n’a pas encore « mûri » pour devenir un objet dérivé. Ainsi, l'implémentation de base originale de value() est appelée.

Comment résoudre le problème

Pour que le code s'imprime 1, vous pouvez éviter d'appeler la fonction virtuelle dans le constructeur. Ceci peut être réalisé par :

  1. Utilisation d'un pointeur : Appelez la fonction virtuelle à partir d'un pointeur ou d'une référence à la classe de base au lieu de directement à partir de sa fonction membre :

    base* b = new derived();
    b->value(); // Calls the derived class implementation
    
    delete b;
    Copier après la connexion
  2. Utilisation d'une liste d'initialisation de membre : Utiliser un membre liste d'initialisation pour spécifier explicitement la valeur de la fonction virtuelle dans le constructeur :

    derived d : base() { } // Initializes `base()` and the virtual function
                           // call to occur within the constructor
    Copier après la connexion
  3. 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 de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal