Dlaczego muszę ponownie zadeklarować przeciążone funkcje wirtualne?
Mam klasę bazową z dwiema przeciążonymi funkcjami f(void)
i f(int)
. Klasa Derived
implementuje f(int)
przez wywołanie f(void)
. tylko Derived2
narzę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
Derived::f
ukrywa Base::f
s. Podana return f();
w treści Derived::f(int)
, nazwa f
znajduje się w zakresie Derived
, a następnie wyszukiwanie nazw zostaje zatrzymane. Nazwy w Base
nie 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 Base
zakresu 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();}
};