【问题标题】:Confusion about the phenomenon of overriding对覆盖现象的困惑
【发布时间】:2020-11-01 18:55:30
【问题描述】:

我对什么时候说该函数被覆盖有点困惑。

我的书说“当派生类创建一个具有相同返回类型和签名的函数时 基类中的成员函数,但有一个新的实现,据说它是覆盖的 那个函数。”

我很清楚书在说什么,但我的问题是,如果我只保持名称相同并更改返回类型和签名,我可以说该函数被覆盖还是有任何不同的术语? 就像我尝试了以下代码:

#include <iostream>
 using namespace std;
 class Mammal
{
 public:
  int Move() const  
   { 
    cout << "mammal moving\n"; 
    return 1; 
   }
   
  void Move(int x) const 
   {
    cout << "walked " << x << " steps\n"; 
   }
};
  
 class Dog : public Mammal
{
 public:
  void Move()
  { 
   cout << "Dog moving\n";
  }
};
  
 int main()
{
 Dog Moti;
 Moti.Move();
//Moti.Move(2);  error: no matching function for call to 'Dog::Move(int)'
 cout << endl;
 return 0; 
}

输出:狗移动

所以我在 Dog 中有 Move() 方法,但它的返回类型和签名与 Mammal 中的 Move() 方法不同。所以说 Dog 中的 Move() 覆盖了 Mammal 中的 Move() 是否正确。为什么我会感到困惑是因为当我打电话给Moti.Move(2) 时,我收到了错误消息。这意味着Mammal 中的void Move(int x) const 被隐藏了。但是,当基类中的重载方法之一在派生类中被覆盖时,就会发生“隐藏”现象。所以这就是为什么我认为“Dog 中的 Move() 已经覆盖了 Mammal 中的 Move()”,但根据书籍定义,这似乎是错误的。

我做了一些互联网搜索,发现“如果是虚拟函数,返回类型必须相同或协变”,但我的问题与虚拟函数或任何东西无关。我只是很困惑我可以说上面的代码中发生了覆盖还是有任何不同的术语。

【问题讨论】:

  • 你只能override一个虚函数。用于您所做的事情的术语是遮蔽或隐藏。
  • 提供同名不同签名的函数是重载。如果这是在派生类中完成的(与基类中的函数同名,但签名不同),派生类中的版本也会隐藏基版本。
  • 你在用什么书?您可以使用 Moti.Mammal::Move(2); 调用其他 Move 方法。
  • Jesse Liberty 在 21 天内自学 C++(第 385 页)

标签: c++ overriding


【解决方案1】:

上面代码中的问题让我想起了一个非常有趣的 CPP 概念,Name Hiding,它简单地说,如果我们尝试在派生类中重载方法,那么编译器将隐藏基类类方法,除非我们显式通知编译器包含基类方法,或者我们使用范围解析运算符(如Moti.Mammal::Move(2);)显式调用基类方法

查看一些相关文章:

https://bastian.rieck.me/blog/posts/2016/name_hiding_cxx/

overloading base class method in derived class

https://www.geeksforgeeks.org/g-fact-89/

P.S:我们不能重载基于返回类型的方法,如果我们尝试这样做会出错。

【讨论】:

    猜你喜欢
    • 2014-05-09
    • 2011-02-26
    • 2012-05-22
    • 2011-01-05
    • 2010-11-23
    • 1970-01-01
    • 1970-01-01
    • 2016-06-10
    • 1970-01-01
    相关资源
    最近更新 更多