En C ++, une fonction est-elle automatiquement virtuelle si elle remplace une fonction virtuelle?

StackOverflow https://stackoverflow.com/questions/1404797

  •  05-07-2019
  •  | 
  •  

Question

Je m'attendrais à ce que si foo soit déclaré dans la classe D , mais non marqué comme virtuel, le code suivant appelle alors l'implémentation de foo dans D (quel que soit le type dynamique de d ).

D& d = ...;
d.foo();

Cependant, dans le programme suivant, ce n'est pas le cas. Quelqu'un peut-il expliquer cela? Une méthode est-elle automatiquement virtuelle si elle remplace une fonction virtuelle?

#include <iostream>

using namespace std;

class C {
public:
        virtual void foo() { cout << "C" << endl; }
};

class D : public C {
public:
        void foo() { cout << "D" << endl; }
};

class E : public D {
public:
        void foo() { cout << "E" << endl; }
};

int main(int argc, char **argv)
{
        E& e = *new E;
        D& d = *static_cast<D*>(&e);
        d.foo();
        return 0;
}

Le résultat du programme ci-dessus est:

E
Était-ce utile?

La solution

La norme 10.3.2 (class.virtual) dit:

  

Si une fonction membre virtuelle vf est déclarée dans une classe Base et dans une classe Dérivée, dérivée directement ou indirectement de Base, une fonction membre vf avec le même nom et la même liste de paramètres que Base :: vf est déclarée, alors Dérivé :: vf est aussi virtuel (qu'il soit ou non déclaré ainsi) et écrase * *

     

[Note de bas de page: une fonction portant le même nom mais une liste de paramètres différente (clause terminée) en tant que fonction virtuelle n'est pas nécessairement virtuelle et ne remplace pas. L'utilisation du spécificateur virtuel dans la déclaration d'une fonction prioritaire est légale mais redondante (avec une sémantique vide). Le contrôle d'accès (clause class.access) n'est pas pris en compte dans la détermination du remplacement. --- mettre fin au foonote]

Autres conseils

La réponse rapide est peut-être non, mais la réponse correcte est oui

.

C ++ ne connaît pas le masquage de fonction, il est donc important de remplacer une fonction virtuelle sans les marques de mot-clé virtuelles qui le font également.

Vous ne créez aucune copie de l'objet de e et ne le placez pas dans d. Donc, d.foo () suit le comportement polymorphe normal et appelle la méthode de la classe dérivée. Une méthode déclarée virtuelle dans la classe de base devient automatiquement virtuelle dans la classe dérivée également.

La sortie ("E") se comporte exactement comme on pourrait s'y attendre.

La raison: Le type dynamique (exécution) de cette référence est E. Vous effectuez une conversion ascendante statique en D, mais cela ne modifie pas le type réel de l'objet, bien sûr.

C'est l'idée même derrière les méthodes virtuelles et les dépêches dynamiques: vous voyez le comportement du type que vous instanciez, qui est E, dans ce cas.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top