Pourquoi ai-je besoin de redéclarer les fonctions virtuelles surchargées?

Nov 26 2020

J'ai une classe de base avec deux fonctions surchargées f(void)et f(int). La classe Derivedimplémente f(int)en appelant f(void). Derived2outils 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

5 songyuanyao Nov 26 2020 at 08:18

Derived::fcache Base::fs. Donné return f();dans le corps de Derived::f(int), le nom fse trouve dans la portée de Derived, puis la recherche de nom s'arrête. Les noms dans Basene 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 Basedans 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();}
};