考虑以下代码
class X{
public:
virtual void foo(X x){ }
virtual void foo(int index){ }
};
class Y : public X{
public:
void foo(int index){ }
};
int main(){
Y y;
y.foo(X()); //Error, see below
}
类X
重载了虚拟foo
方法。一个版本需要X
,另一个版本需要int
。现在,类Y
继承自X
并覆盖方法foo(int)
。方法foo(X)
不会被覆盖,它应该保持不变。
但是,在Y
方法中创建main
类型的对象并调用foo(X)
时,编译器会抱怨以下内容:
In function ‘int main()’:
error: no matching function for call to ‘Y::foo(X)’
note: candidate is:
note: virtual void Y::foo(int)
note: no known conversion for argument 1 from ‘X’ to ‘int’
因此,唯一的候选者是被覆盖的foo(int)
方法。似乎另一种方法已经消失了。如果我删除了覆盖版本,即将Y
声明为public Y : public X{};
,那么一切正常。为什么会这样?
答案 0 :(得分:5)
当派生类定义的成员与基类中的相同名称的成员时,派生类名称会隐藏基类名称。
在您的情况下,函数Y::foo
隐藏 X::foo
。您需要将其纳入Y
范围:
class Y : public X{
public:
using X::foo; //it brings X::foo into the scope of Y
void foo(int index){ }
};
答案 1 :(得分:1)
重载适用于在同一范围内定义的名称 。因此,类foo
中的Y
不会使类foo
中的X
重载,因为它们在不同的范围内定义。这被非正式地称为“名字隐藏”。要将基类名称拉入派生类,请添加using指令:
using X::foo;