【问题标题】:C++: override or overload?C++:覆盖还是重载?
【发布时间】:2016-08-26 08:52:44
【问题描述】:

我有两个类代表某些方法的上下文。

class BaseContext {};
class DerivedContext : public BaseContext {};

我有一个基类:

class MyBase {
protected:
  virtual void doSome(BaseContext* context);
};

还有一个派生类:

class MyDerived : public MyBase {
protected:
  virtual void doSome(DerivedContext* context) override; // Overriding
  virtual void doSome(DerivedContext* context); // Overloading?
};

由于DerivedContext 派生自BaseContext,看来我正在覆盖doSome。但它也可能是一个重载......

  1. 哪一个是正确的?我是在这里覆盖还是重载?
  2. 因此,如果我输入(MyBase* my = new MyDerived())->doSome(new DerivedContext()),我应该得到什么?

【问题讨论】:

  • 您的派生类型有两个相同的方法 - override 不会更改类型 - 这是不允许的。他们中的一个人应该接受BaseContext 论点吗?

标签: c++ overloading overriding


【解决方案1】:

这既不是覆盖也不是重载。由于参数的类型不同,MyDerived::doSome 只是隐藏 MyBase::doSome

1.1。由于DerivedContext 派生自BaseContext,看来我正在覆盖doSome

没有。这是标准中列出的覆盖的先决条件。 $10.3/2 Virtual functions [class.virtual]:

(强调我的)

如果在类Base和类Derived中声明了一个虚成员函数vf,直接或间接派生自Base,则一个同名的成员函数vf parameter-type-list ([dcl.fct])、cv-qualification 和 ref-qualifier(或不存在相同的)作为 Base::vf 被声明,那么 Derived::vf 也是虚拟的(无论是否如此声明)并且它覆盖110Base::vf

110)作为虚函数的同名但参数列表不同的函数(子句[over])不一定是虚函数,不会覆盖

事实上,override specifier 在这种情况下你会得到一个compile error。例如

error: 'doSome' marked 'override' but does not override any member functions

1.2。但它也可能是一个重载......

can't overload 根据unqualified name lookup 的规则跨范围运行(除非使用using-declaration 将名称引入同一范围)。

  1. 因此,如果我输入(MyBase* my = new MyDerived())->doSome(new DerivedContext()),我应该得到什么?

MyBase::doSome() 将被调用,因为您在 MyBase* 上调用它。这不是覆盖,因此这里不会发生动态调度。

LIVE

注意参数DerivedContext*会隐式转换为BaseContext*,然后传递给函数。 BTW (MyBase* my = new MyDerived())->... 语法无效。

【讨论】:

  • 我不认为它是隐藏的。你仍然可以调用 doSome(BaseContext*) 。
  • @WikiWang 你不能在MyDerived 上调用它。见rextester.com/HMLR15127
  • @WikiWang 您必须将 using MyBase::doSome; 添加到 MyDerived 以恢复基本过载。
  • @songyuanyao 好吧,源代码标记了那些受保护的函数,您可以在 MyDerived::some_function 中使用 MyBase::doSome(...) 调用它。
  • @WikiWang 是的,你不能叫它doSome(...),你必须叫它MyBase::doSome(...),这就是所谓的名字隐藏。
【解决方案2】:

虽然仅使用其他参数类型指定成员函数,但您正在从基类中隐藏该函数。
使用override 说明符,您应该会收到编译错误,因为基类中没有这样的函数(具有完全相同的签名)。

重写是指重新定义在派生类中使用完全相同的参数(数字 类型)。 override 说明符是可选的,但鼓励使用,因为它有助于识别您的情况中的细微错误。

重载是在定义具有不同数量或类型参数的函数(不一定是类的成员)时。

【讨论】:

  • "或在派生类中重新定义非虚拟成员函数。"它仍在隐藏,而不是超载。
【解决方案3】:

只需在函数定义后加上 override 看看它是否可以编译。如果它编译,它将覆盖基类中的虚拟方法。如果没有,它将隐藏基类方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-01
    • 2020-05-11
    相关资源
    最近更新 更多