考虑以下示例:
struct Base
{
virtual void fun() = 0;
void fun(float) { fun(); }
};
struct Derived : Base
{
void fun() override {}
void bar()
{
// calling Base1::fun from, which in turn should call Derived::fun
fun(42.42f); // error "Function does not take 1 argument"
Base::fun(42.42f); // ok
}
};
为什么在这种情况下需要指定fun
的范围?不应该隐含地考虑基类fun
吗?
为什么删除Derived::fun
的定义会导致编译成功?
答案 0 :(得分:3)
不会通过不同的范围进行重载。
对于fun(42.42f);
,必须找到名称fun
。根据{{3}}的规则:
对于非限定名称,即不在范围解析运算符::右侧显示的名称,名称查找检查范围如下所述,直到它找到至少一个任何类型的声明,此时查找停止,不再检查其他范围。
这意味着名称将在班级Derived
的范围内找到,即Derived::fun()
。然后名称查找停止,Base
范围内的名称将完全不被考虑。
如果删除Derived::fun
的定义,则Derived
的范围内不会找到任何名称,那么将进一步检查基类的范围(即Base
)并且会找到Base::foo
。一切正常。
值得注意的是unqualified name lookup在名字查找后发生。
答案 1 :(得分:2)
这是因为 Method Hiding 引起的,即使签名有所不同也很难。正如一些程序员提到的那样“如果你在一个已经存在于基类中的子类中使用一个成员的符号,那么基类中的符号就会被隐藏”。
请在Why does an overridden function in the derived class hide other overloads of the base class?
中阅读更多内容