J'ai une fonction avec le même nom, mais avec une signature différente dans une base et des classes dérivées. Lorsque j'essaie d'utiliser la fonction de la classe de base dans une autre classe qui hérite du dérivé, je reçois une erreur. Voir le code suivant:
class A
{
public:
void foo(string s){};
};
class B : public A
{
public:
int foo(int i){};
};
class C : public B
{
public:
void bar()
{
string s;
foo(s);
}
};
Je reçois l'erreur suivante du compilateur gcc:
In member function `void C::bar()': no matching function for call to `C::foo(std::string&)' candidates are: int B::foo(int)
Si je supprime int foo(int i){};
de la classe B
ou si je la renomme foo1
, tout fonctionne bien.
Quel est le problème avec ça?
Réponses:
Les fonctions des classes dérivées qui ne remplacent pas les fonctions des classes de base mais qui ont le même nom masqueront les autres fonctions du même nom dans la classe de base.
Il est généralement considéré comme une mauvaise pratique d'avoir des fonctions dans des classes dérivées qui ont le même nom que des fonctions de la classe de basse qui ne sont pas destinées à remplacer les fonctions de classe de base car ce que vous voyez n'est généralement pas un comportement souhaitable. Il est généralement préférable de donner à différentes fonctions des noms différents.
Si vous devez appeler la fonction de base, vous devrez étendre l'appel à l'aide de
A::foo(s)
. Notez que cela désactiverait également tout mécanisme de fonction virtuelle pourA::foo(string)
en même temps.la source
C'est parce que la recherche de nom s'arrête si elle trouve un nom dans l'une de vos bases. Il ne cherchera pas au-delà dans d'autres bases. La fonction de B masque la fonction de A. Vous devez re-déclarer la fonction de A dans la portée de B, de sorte que les deux fonctions soient visibles depuis B et C:
Edit: La vraie description que donne la norme est (à partir de 10.2 / 2):
Il a ce qui suit à dire à un autre endroit (juste au-dessus):
([...] mis par moi). Notez que cela signifie que même si votre toto dans B est privé, le toto dans A ne sera toujours pas trouvé (car le contrôle d'accès se produit plus tard).
la source
void A::foo(class basic_string<char,char_traits<char>,allocator<char> >)' in
classe B 'à cause de la méthode locale `int B :: foo (int)' avec le même nom. C'est peut-être parce que j'utilise une ancienne version de gcc