2009-12-13 7 views
53

J'ai écrit le code ci-dessous afin d'expliquer mon problème. Si je commente la ligne 11 (avec le mot-clé "using"), le compilateur ne compile pas le fichier et affiche cette erreur: invalid conversion from 'char' to 'const char*'. Il semble ne pas voir la méthode void action(char) de la classe Parent dans la classe Son.Pourquoi devrais-je utiliser le mot-clé "using" pour accéder à ma méthode de classe de base?

Pourquoi le compilateur se comporte-t-il de cette façon? Ou ai-je fait quelque chose de mal?

class Parent 
{ 
    public: 
     virtual void action(const char how){ this->action(&how); } 
     virtual void action(const char * how) = 0; 
}; 

class Son : public Parent 
{ 
    public: 
     using Parent::action; // Why should i write this line? 
     void action(const char * how){ printf("Action: %c\n", *how); } 
}; 

int main(int argc, char** argv) 
{ 
    Son s = Son(); 
    s.action('a'); 
    return 0; 
} 
+0

S'il vous plaît dites-moi: et si vous supprimez const dans "const char comment"? –

+24

Vous n'avez pas besoin de taper 'Son s = Son();'. Cela crée juste un temporaire et appelle ensuite le constructeur de copie. Il suffit de taper 'Fils s;' –

+3

Nous avons cette question beaucoup: [http://stackoverflow.com/questions/1835988](http://stackoverflow.com/questions/1835988) [http://stackoverflow.com/ questions/411103] (http://stackoverflow.com/questions/411103) [http://stackoverflow.com/questions/1480085](http://stackoverflow.com/questions/1480085) [http: // stackoverflow. com/questions/1799497] (http://stackoverflow.com/questions/1799497) [http://stackoverflow.com/questions/888235](http://stackoverflow.com/questions/888235) [http: // stackoverflow.com/questions/72010](http://stackoverflow.com/questions/72010) –

Répondre

47

Le action déclaré dans la classe dérivée cache le action déclaré dans la classe de base. Si vous utilisez action sur un objet Son le compilateur cherchera dans les méthodes déclarées dans Son, en trouver un appelé action, et l'utiliser. Il ne va pas chercher dans les méthodes de la classe de base, puisqu'il a déjà trouvé un nom correspondant.

Ensuite, cette méthode ne correspond pas aux paramètres de l'appel et vous obtenez une erreur.

Voir aussi C++ FAQ pour plus d'explications à ce sujet.

+8

@sth Bon à savoir. mais est-ce, peut-on dire, une caractéristique de C++ ou une sorte de bug? cela ne gâte-t-il pas toute l'idée de l'héritage? il suffit de demander .. – Anubis

+0

Est-ce que le nom correspondant est fait en utilisant le nom mutilé, est-ce que la surcharge de méthode joue un rôle ici, ou est-ce que la première fonction appelée a le nom "action" et c'est tout? – tmaric

+3

@Anubis: La règle simplifie la recherche de nom. Sans cela, le compilateur aurait besoin de parcourir l'arbre d'héritage complet lorsqu'il doit résoudre le nom d'une fonction membre (il pourrait y avoir des surcharges de la fonction dans une classe de base).Avec la règle, le compilateur peut arrêter de regarder le reste de l'arbre d'héritage une fois qu'il a trouvé une classe contenant un nom d'ajustement. Le programmeur est dans la même situation. En regardant la classe dérivée, il peut être sûr que la fonction définie ici sera appelée, sans avoir à savoir si une classe de base peut contenir une fonction différente du même nom. – sth

15

De façon surprenante, ceci est un comportement standard. Si une classe dérivée déclare une méthode avec le même nom qu'une méthode définie par la classe de base, la méthode de la classe dérivée cache celle de la classe de base.

Voir C++ FAQ

5

Une note d'avertissement: La nécessité d'utiliser un "using" dans cette situation est un drapeau rouge que votre code peut être source de confusion pour les autres développeurs (après tout, il a confondu le compilateur!). Il est probable que vous deviez renommer l'une des deux méthodes pour rendre la distinction claire aux autres programmeurs.

Une possibilité:

void action(const char how) 
{ 
    takeAction(&how); 
} 
void action(const char * how) 
{ 
    takeAction(how); 
} 
virtual void takeAction(const char * how) = 0; 
3

Si dans une classe dérivée une fonction plus chargée est ensuite redéfini toute la fonction surchargée dans la classe de base est cachée. Une façon d'inclure à la fois la fonctionnalité est d'éviter la surcharge de fonctions dans les classes. ou Vous pouvez utiliser le mot-clé using, tel qu'utilisé.