为什么动态绑定可以覆盖 C++ 中的名称隐藏?

Why can dynamic binding override name hiding in C++?

我了解到内部名称隐藏外部名称(因此重载不会跨范围),因为名称查找在类型匹配之前进行。所以我写了下面的 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': function does not take 0 arguments

你能帮我解释一下这个现象吗?具体来说,动态绑定是否可以像我假设的那样覆盖名称隐藏?如果是这样,如果指针指向派生 class,为什么覆盖会失败?谢谢。

名称查找(和重载解析)发生在编译时。

给定 bp->fcn,如果 bp 的类型是 Base*,名称查找将检查 Base 的范围,然后找到名称 Base::fcn . bp 指向 Derived 的对象这一事实不涉及 DerivedDerived::fcn 的范围。动态调度发生在 运行 时间,如果 Derived 有一个覆盖的 Derived::fcn() 它将在 运行 时间被调用。

如果 bp 的类型是 Derived*,名称查找将检查 Derived 的范围,然后找到名称 Derived::fcn,然后名称查找停止, Base 的范围将不再进一步检查;名字隐藏发生了。