2017-03-15 4 views
3

Cette question m'a été posée lors d'une interview. Je n'étais pas capable de répondre à cela. Je ne suis pas non plus capable de l'obtenir maintenant, pour savoir pourquoi la sortie est telle qu'elle est. Voici le code:Surcharge de fonctions virtuelles

#include <iostream> 
using namespace std; 

class Base 
{ 
public: 
    virtual void fun (int x = 0) 
    { 
     cout << "Base::fun(), x = " << x << endl; 
    } 
}; 

class Derived : public Base 
{ 
public: 
    virtual void fun (float x = 10.0) 
    { 
     cout << "Derived::fun(), x = " << x << endl; 
    } 
}; 


int main() 
{ 
    Derived d1; 
    Base *bp = &d1; 
    bp->fun(); 
    d1.fun(); 
    d1.fun(1.2); 
    return 0; 
} 

La sortie du code ci-dessus est:

Base::fun(), x = 0 
Derived::fun(), x = 10 
Derived::fun(), x = 1.2 

Le problème est: Dans le premier cas, nous disons que les deux fonctions fun() surchargé (et non pas puisque ils diffèrent dans leurs déclarations) et le plaisir de base() est appelée, mais il est impossible pour ces déclarations de plaisir() à être surchargées (car ils ne diffèrent si la déclaration contient argument par défaut ou non)

void fun(int x = 0) 
void fun(float x = 10.0) 

Il est impossible que ces fonctions sont surchargés.

Il semble y avoir une contradiction dans les deux cas ci-dessus.

Tout article/lien associé expliquant la situation serait très utile.

+0

Qu'attendez-vous de la sortie et pourquoi? – NathanOliver

+0

Dans le premier cas, la sortie devrait être, Derived :: fun(), x = 10.0, en raison du polymorphisme d'exécution. Dans le deuxième et le troisième cas, comment décidez-vous la sortie? –

Répondre

8

En C++, pour une fonction membre de passer outre une fonction de classe de base, les types d'arguments doivent correspondre exactement aux types d'arguments de la fonction de la classe de base. Comme la fonction de classe de base prend un int et que la fonction de votre classe dérivée prend un float, elle n'est pas considérée comme un remplacement. Vous pouvez voir cela en utilisant le override mot-clé:

class Base 
{ 
public: 
    virtual void fun (int x = 0) 
    { 
     cout << "Base::fun(), x = " << x << endl; 
    } 
}; 

class Derived : public Base 
{ 
public: 
    virtual void fun (float x = 10.0) override // Doesn't compile! 
    { 
     cout << "Derived::fun(), x = " << x << endl; 
    } 
}; 

Qu'est-ce qui se passe dans votre code est que C++ considère que votre fonction soit une surcharge (une autre fonction du même nom) plutôt que d'une override. Regardons ce code:

Derived d1; 
Base *bp = &d1; 
bp->fun(); 

Ici, depuis la ligne bp->fun() utilise un appel via un pointeur de classe de base, C++ regarde dans Base pour voir la fonction à appeler. Il trouve Base::fun(int). Maintenant, puisque cette fonction est marquée virtual, il appellera Base::fun(int) à moins que quelque chose l'ait outrepassé. Mais puisqu'il n'y a pas de dérogation, Base::fun(int) finit par être invoqué.

Alors, que sur ces deux lignes plus tard?

d1.fun(); 
d1.fun(1.2); 

ici, puisque vous appelez ces fonctions sur des objets de type statique Derived, C++ tente de trouver une fonction appelée fun dans la classe Derived. Il trouve votre nouvelle fonction Derived::fun(float), et en raison de la manière dont C++ recherche les noms dans les classes, il ne regarde pas dans la classe de base pour trouver Base::fun(int). Par conséquent, ces deux appels sont traités comme des appels au Derived::fun(float), il n'y a donc aucune ambiguïté quant à la fonction à appeler quand aucun argument n'est présenté. Le compilateur n'a même jamais regardé dans le type Base car il n'y en avait pas besoin.

Donc, pour résumer:

  • Vous avez introduit une surcharge , pas override. L'utilisation du mot-clé override vous aidera à diagnostiquer des problèmes de ce type dans le futur.
  • Appel fun par le pointeur de base cherche une fonction nommée fun prendre dans un int, puisque fun fonction du pointeur de base prend dans un int. Cela trouve la version dans Base parce qu'il n'y a pas d'erreur.
  • L'appel fun à travers l'objet dérivé recherche une fonction nommée fun commençant à Derived, et il trouve votre remplacement.
+0

Dans le premier cas, pourquoi le polymorphisme d'exécution n'est pas là? –

+1

@YamanSingla Juste mis à jour la réponse pour expliquer ce qui se passe. – templatetypedef

+0

Merci beaucoup pour l'aide @templatetypedef. J'ai compris maintenant ce qui se passe réellement! –