Pourquoi ai-je besoin de redéclarer les fonctions virtuelles surchargées?
J'ai une classe de base avec deux fonctions surchargées f(void)
et f(int)
. La classe Derived
implémente f(int)
en appelant f(void)
. Derived2
outils f(void)
uniquement.
Le compilateur rejette l'implémentation Derived::f(int)
parce qu'il veut appeler f(int)
mais je n'ai fourni aucun argument parce que je veux appeler f(void)
. Pourquoi le compilateur le rejette-t-il? Pourquoi l'ajout de la ligne résout virtual int f(void) = 0;
mon problème?
class Base
{
public:
explicit Base(void) {}
virtual ~Base(void) {}
virtual int f(void) = 0;
virtual int f(int i) = 0;
};
class Derived : public Base
{
public:
// provide implementation for f(int) which uses f(void). Does not compile.
virtual int f(int i) {puts("Derived::f(int)"); return f();}
// code only compiles by adding the following line.
virtual int f(void) = 0;
};
class Derived2 : public Derived
{
public:
// overwrite only f(void). f(int) is implemented by Derived.
virtual int f(void) {puts("Derived2::f(void)"); return 4;}
};
int main(void)
{
Base * p = new Derived2();
int i0 = p->f(); // outputs Derived2::f(void) and returns 4
int i1 = p->f(1); // outputs "Derived::f(int) Derived2::f(void)" and return 4
delete p;
return 0;
}
Réponses
Derived::f
cache Base::f
s. Donné return f();
dans le corps de Derived::f(int)
, le nom f
se trouve dans la portée de Derived
, puis la recherche de nom s'arrête. Les noms dans Base
ne seront pas trouvés et participeront à la résolution de surcharge.
name lookup examine les portées comme décrit ci-dessous, jusqu'à ce qu'il trouve au moins une déclaration de n'importe quel type, moment auquel la recherche s'arrête et aucune autre portée n'est examinée.
Vous pouvez ajouter using Base::f;
pour introduire le nom Base
dans la portée de Derived
.
class Derived : public Base
{
public:
using Base::f;
// provide implementation for f(int) which uses f(void).
virtual int f(int i) {puts("Derived::f(int)"); return f();}
};