2012-06-03 1 views
7

Quelqu'un peut-il expliquer pourquoi le résultat du code ci-dessous serait "class B :: 1"?Le code exécute la méthode de la classe dérivée, mais obtient le paramètre par défaut de la méthode de la classe de base

Pourquoi la méthode virtuelle de la classe dérivée utilise-t-elle le paramètre par défaut d'une classe de base et non le sien? Pour moi, c'est assez étrange. Merci d'avance!

code:

#include <iostream> 

using namespace std; 

class A 
{ 
public: 
    virtual void func(int a = 1) 
    { 
     cout << "class A::" << a; 
    } 
}; 

class B : public A 
{ 
public: 
    virtual void func(int a = 2) 
    { 
     cout << "class B::" << a; 
    } 
}; 

int main() 
{ 
    A * a = new B; 
    a->func(); 

    return 0; 
} 

Répondre

6

Parce que les arguments par défaut sont résolus en fonction du type statique de l'appelant. this (c'est-à-dire, le type de la variable elle-même, comme A& dans A& a;).

Modifier votre exemple légèrement:

#include <iostream> 

class A 
{ 
public: 
    virtual void func(int a = 1) 
    { 
     std::cout << "class A::" << a << "\n"; 
    } 
}; 

class B : public A 
{ 
public: 
    virtual void func(int a = 2) 
    { 
     std::cout << "class B::" << a << "\n"; 
    } 
}; 

void func(A& a) { a.func(); } 

int main() 
{ 
    B b; 
    func(b); 
    b.func(); 

    return 0; 
} 

Nous observons la sortie suivante:

class B::1 
class B::2 

en action à ideone.

Il n'est pas recommandé qu'une fonction virtuelle modifie la valeur par défaut pour cette raison. Malheureusement, je ne connais aucun compilateur qui avertit sur cette construction.


L'explication technique est qu'il ya deux façons de traiter avec l'argument par défaut:

  • créer une nouvelle fonction d'agir comme trampoline: void A::func() { func(1); }
  • complément l'argument manquant à l'appel Site a.func() =>a.func(/*magic*/1)

Si elle était l'ancien (et en supposant que le A::func w comme déclaré virtual ainsi), alors cela fonctionnerait comme prévu. Cependant, cette dernière forme a été élue, soit parce que les questions avec virtual n'étaient pas prévues à ce moment-là, soit parce qu'elles étaient jugées sans conséquence face aux avantages (le cas échéant ...).

5

Parce que la valeur par défaut est remplacée lors de la compilation et est tirée de la déclaration, en fonction réelle à appeler (A ou B :: func :: func) est déterminée lors de l'exécution.

+0

Merci pour la réponse rapide! – Aremyst

5

Parce que le polymorphisme en C++ prend effet à l'exécution, alors que la substitution des paramètres par défaut prend effet à la compilation. Au moment de la compilation, le compilateur ne sait pas (et n'est pas censé connaître) le type dynamique de l'objet sur lequel pointe le pointeur a. Par conséquent, il prend l'argument par défaut pour le seul type qu'il connaît pour a, ce qui dans votre exemple est A *.

(Ceci est d'ailleurs également les paramètres par défaut de raison sont données dans les interfaces/en-têtes plutôt que dans les implémentations/définitions. Le compilateur insère jamais le paramètre par défaut dans le code machine de la mise en œuvre, mais seulement dans le code de la machine de l'appelant . Techniquement le paramètre par défaut est la propriété de l'appelant et l'appelant ne sait pas - et ne devrait pas avoir besoin de connaître - le type dynamique d'un objet.)

+0

Votre réponse est très claire, merci! – Aremyst

Questions connexes