web-dev-qa-db-fra.com

Remplacement des méthodes non virtuelles

Supposons ce scénario dans Visual C++ 2010:

#include <iostream>
#include <conio.h>

using namespace std;

class Base
{
public:
    int b;
    void Display()
    {
        cout<<"Base: Non-virtual display."<<endl;
    };
    virtual void vDisplay()
    {
        cout<<"Base: Virtual display."<<endl;
    };
};

class Derived : public Base
{
public:
    int d;
    void Display()
    {
        cout<<"Derived: Non-virtual display."<<endl;
    };
    virtual void vDisplay()
    {
        cout<<"Derived: Virtual display."<<endl;
    };
};

int main()
{
    Base ba;
    Derived de;

    ba.Display();
    ba.vDisplay();
    de.Display();
    de.vDisplay();

    _getch();
    return 0;
};

Théoriquement, le résultat de cette petite application devrait être:

  • Base: affichage non virtuel.
  • Base: affichage virtuel.
  • Base: affichage non virtuel.
  • Dérivé: affichage virtuel.

car la méthode Display de la classe Base n'est pas une méthode virtuelle, la classe Derived ne doit donc pas pouvoir la remplacer. Droite?

Le problème est que lorsque j'exécute l'application, elle affiche ceci:

  • Base: affichage non virtuel.
  • Base: affichage virtuel.
  • Dérivé: affichage non virtuel.
  • Dérivé: affichage virtuel.

Donc, je n'ai pas compris le concept de méthodes virtuelles ou quelque chose d'étrange se produit dans Visual C++.

Quelqu'un pourrait-il m'aider avec une explication?

58
Leif Lazar

Oui, vous vous méprenez un peu.

La méthode du même nom sur la classe dérivée masquera la méthode parent dans ce cas. Vous imaginez que si ce n'était pas le cas, essayer de créer une méthode avec le même nom qu'une méthode non virtuelle de classe de base devrait générer une erreur. C'est autorisé et ce n'est pas un problème - et si vous appelez la méthode directement comme vous l'avez fait, cela s'appellera bien.

Mais, étant non virtuel, les mécanismes de recherche de méthode C++ qui permettent le polymorphisme ne seront pas utilisés. Ainsi, par exemple, si vous avez créé une instance de votre classe dérivée mais appelé votre méthode 'Display' via un pointeur vers la classe de base, la méthode de la base sera appelée, tandis que pour 'vDisplay', la méthode dérivée serait appelée.

Par exemple, essayez d'ajouter ces lignes:

Base *b = &ba;
b->Display();
b->vDisplay();
b = &de;
b->Display();
b->vDisplay();

... et observez la sortie comme prévu:

Base: affichage non virtuel.
Base: affichage virtuel.
Base: affichage non virtuel.
Dérivée: affichage virtuel.

85
sje397

Oui vous avez un peu mal compris:

Fonctions virtuelles pures:

virtual void fun1()=0 -> doit être remplacé dans la classe dérivée

Fonctions virtuelles:

virtual void fun2() -> peut être remplacée

Fonctions normales:

void fun3() -> ne le remplace pas

Pour atteindre le polymorphisme d'exécution, vous devez remplacer les fonctions virtuelles en c ++

5
Avinash Aitha

Je pense qu'il pourrait aussi être préférable de l'examiner dans le contexte de la liaison statique vs dynamique.

Si la méthode n'est pas virtuelle (elle est déjà par défaut en C++ contrairement à Java), alors la méthode se lie à son appelant au moment de la compilation, ce qui est impossible de connaître l'objet réel qui sera pointé au moment de l'exécution. Ainsi, le type de variable est tout ce qui compte, c'est la "Base".

3
stdout