我了解到内部名称隐藏了外部名称(因此重载不会跨越范围),因为名称查找在类型匹配之前进行。所以我编写以下C ++代码来使用此规则:
class Base {
public:
virtual void fcn() {}
};
class Derived : public Base {
public:
void fcn(std::string s) {}
};
Base* bp = new Derived;
bp->fcn();
delete bp;
根据隐藏规则,Derived::fcn(std::string)
函数应隐藏Base::fcn()
。但是上面的代码在违反规则的情况下编译并正确运行。这是否意味着动态绑定可以覆盖隐藏在C ++中的名称?问题是,如果我将bp
的类型更改为Derived*
,隐藏规则会通过发出编译错误来实现:
'Derived :: fcn':函数不带0个参数
你能帮我解释一下这个现象吗?具体来说,动态绑定可以覆盖我假设的隐藏名称吗?如果是这样,为什么如果指针指向派生类,覆盖会失败?谢谢。
名称查找(和重载解析)在编译时发生。
鉴于bp->fcn
,如果bp
的类型是Base*
,名称查找将检查Base
的范围,然后找到名称Base::fcn
。 bp
指向Derived
的对象的事实不涉及Derived
和Derived::fcn
的范围。动态调度在运行时发生,如果Derived
有一个覆盖的Derived::fcn()
,它将在运行时被调用。
如果bp
的类型是Derived*
,名称查找将检查Derived
的范围,然后找到名称Derived::fcn
,然后名称查找停止,Base
的范围将不再进一步检查;名字隐藏发生。