我目前正在尝试理解C ++继承中隐藏名称的东西。
我在C ++ primer plus上阅读了这篇文章,第744页
简而言之,重新定义继承的方法不是重载的变体。如果在派生类中重新定义函数,它不会仅使用相同的函数签名覆盖基类声明。相反,它隐藏了所有同名的基类方法,无论参数签名如何。
所以我试过,这是我的两个类,Base和Derived
void Base::output(string x)
根据该书,Derived* x = new Derived();
x->output(7);
将被重新定义,并且将隐藏具有相同名称的所有其他成员函数。
但以下两个代码讲述了不同的故事。
Base* x = new Derived();
x->output(7);
此代码无法按预期编译,错误消息为
没有可行的从'int'转换为'string'
但如果我喜欢这样,
{{1}}
它神奇地起作用,并给出了以下输出:
Base :: Base()称为
Derived :: Derived()称为
Base :: output(int x)名为
为什么会发生这种情况,指针类型是否真的会影响查找? 顺便说一下,这是在Xcode上。
答案 0 :(得分:1)
对于此代码:
Derived* x = new Derived();
x->output(7);
编译器将首先尝试解析该函数,并且它看到Derived有一个名为output的函数。一旦找到它,编译器就不会再看了。然后它将解析参数并看到参数不正确并失败。
无论哪种方式,后期绑定都不适用于此,因为您使用Derived类指针来访问基类中的函数。你必须向上投射。
对于此代码:
Base* x = new Derived();
x->output(7);
编译器看到x是Base类型,其函数的参数为int。编译器解析了该函数并进行了设置。如果你要覆盖多态行为的函数,这将是适当的用法。
请注意,您可以调用x->输出("是");并调用正确的函数;这将是衍生版本。这是使用vtable的地方。
由于编译器这样做的原因,请查看"脆弱的基类问题"。
答案 1 :(得分:0)
使用时
Base* x = new Derived();
x->output(7);
编译时不会查找Derived
中的函数。在编译时只查找Base
中的函数。因此,它有效。
当
x->output(7);
处理后,我们对x
类型的唯一了解就是它是Base*
。在编译时不考虑它确实指向Derived
对象的事实。在编译时,该调用将解析为Base::outout(int)
。由于Base::output(int)
未覆盖Derived
,因此Base::output(int)
也会在运行时执行。如果有Derived::output(int)
,它将在运行时执行。
答案 2 :(得分:0)
是的,指针类型会影响查找 - 这是拥有类型的重点。当您定义<small>
时,所有编译器都知道它将指向Base*
类型的对象,甚至不会考虑Base
的可能性。