为什么基类函数没有被具有相同名称的派生类函数隐藏

时间:2016-04-17 21:49:00

标签: c++ inheritance

我目前正在尝试理解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上。

3 个答案:

答案 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的可能性。