Dlaczego muszę ponownie zadeklarować przeciążone funkcje wirtualne?

Nov 26 2020

Mam klasę bazową z dwiema przeciążonymi funkcjami f(void)i f(int). Klasa Derivedimplementuje f(int)przez wywołanie f(void). tylko Derived2narzędzia f(void).

Kompilator odrzuca implementację, Derived::f(int)ponieważ chce wywołać, f(int)ale nie podałem żadnych argumentów, ponieważ chcę wywołać f(void). Dlaczego kompilator to odrzuca? Dlaczego dodanie linii virtual int f(void) = 0;rozwiązuje mój problem?

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

Odpowiedzi

5 songyuanyao Nov 26 2020 at 08:18

Derived::fukrywa Base::fs. Podana return f();w treści Derived::f(int), nazwa fznajduje się w zakresie Derived, a następnie wyszukiwanie nazw zostaje zatrzymane. Nazwy w Basenie zostaną znalezione i będą uczestniczyć w rozwiązywaniu przeciążeń.

wyszukiwanie nazw sprawdza zakresy w sposób opisany poniżej, aż znajdzie przynajmniej jedną deklarację dowolnego rodzaju, po czym wyszukiwanie zostanie zatrzymane i żadne dalsze zakresy nie będą sprawdzane.

Możesz dodać, using Base::f;aby wprowadzić nazwę z Basezakresu 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();}
};