¿Por qué necesito volver a declarar las funciones virtuales sobrecargadas?

Nov 26 2020

Tengo una clase base con dos funciones sobrecargadas f(void)y f(int). La clase se Derivedimplementa f(int)llamando f(void). Derived2implementos f(void)solamente.

El compilador rechaza la implementación Derived::f(int)porque quiere llamar, f(int)pero no proporcioné argumentos porque quiero llamar f(void). ¿Por qué el compilador lo rechaza? ¿Por qué agregar la línea virtual int f(void) = 0;soluciona mi problema?

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;
}

Respuestas

5 songyuanyao Nov 26 2020 at 08:18

Derived::fesconde Base::fs. Dado return f();en el cuerpo de Derived::f(int), el nombre fse encuentra en el alcance de Derived, luego se detiene la búsqueda de nombres . Los nombres en Baseno se encontrarán y participarán en la resolución de sobrecarga.

La búsqueda de nombres examina los ámbitos como se describe a continuación, hasta que encuentra al menos una declaración de cualquier tipo, momento en el que la búsqueda se detiene y no se examinan más ámbitos.

Puede agregar using Base::f;para introducir el nombre de Baseen el alcance 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();}
};