为什么动态绑定可以覆盖 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
的对象这一事实不涉及 Derived
和 Derived::fcn
的范围。动态调度发生在 运行 时间,如果 Derived
有一个覆盖的 Derived::fcn()
它将在 运行 时间被调用。
如果 bp
的类型是 Derived*
,名称查找将检查 Derived
的范围,然后找到名称 Derived::fcn
,然后名称查找停止, Base
的范围将不再进一步检查;名字隐藏发生了。
我了解到内部名称隐藏外部名称(因此重载不会跨范围),因为名称查找在类型匹配之前进行。所以我写了下面的 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
的对象这一事实不涉及 Derived
和 Derived::fcn
的范围。动态调度发生在 运行 时间,如果 Derived
有一个覆盖的 Derived::fcn()
它将在 运行 时间被调用。
如果 bp
的类型是 Derived*
,名称查找将检查 Derived
的范围,然后找到名称 Derived::fcn
,然后名称查找停止, Base
的范围将不再进一步检查;名字隐藏发生了。