为什么我需要重新声明重载的虚函数?
我有一个带有两个重载函数的基类f(void)和f(int). 类Derived工具f(int)调用f(void)。只Derived2执行f(void)。
编译器拒绝实现,Derived::f(int)因为它想调用,f(int)但我没有提供参数,因为我想调用f(void). 为什么编译器拒绝它?为什么添加行可以virtual int f(void) = 0;解决我的问题?
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;
}
回答
Derived::f隐藏Base::f. 鉴于return f();在体内Derived::f(int),这个名字f是在范围中Derived,则名称查找停止。中的名称Base将不会被找到并参与重载解析。
名称查找按如下所述检查作用域,直到找到至少一个任何类型的声明,此时查找停止并且不再检查其他作用域。
您可以添加using Base::f;将名称从Base引入范围内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();}
};