IE盒子

搜索
查看: 154|回复: 0

Modern C++ | 军训第十二条: 声明重写的函数为override

[复制链接]

1

主题

6

帖子

9

积分

新手上路

Rank: 1

积分
9
发表于 2023-1-15 16:36:53 | 显示全部楼层 |阅读模式
重点


  • 将被重写的函数加上修饰符override.
  • 成员函数引用限定符可以区别对待左值和右值对象 (*this).
C++中, 我们可以通过在基类中声明函数为virtual并在派生类中覆盖重写它们来实现多态性. 但是, 很容易忽略一些细节而误入歧途. 编译器甚至可能不会警告我们写错了. 让我们来看一些没能成功被覆盖的错误重写例子:
class Base {
public:
  virtual void mf1() const;
  virtual void mf2(int x);
  virtual void mf3() &;
  void mf4() const;
};

class Derived: public Base {
public:
  virtual void mf1();
  virtual void mf2(unsigned int x);
  virtual void mf3() &&;
  virtual void mf4() const;
}
上面在 Derived 类中声明的 4 个函数都没有成功覆盖它们在 Base 类中的对应函数. 为什么?

  • mf1Base 中被声明为 const,但在 Derived 中没有
  • mf2Base 中入参是 int, 但在 Derived 中是 unsigned int
  • mf3Base 中是左值限定的, 但在 Derived 中是右值限定的
  • mf4 未在 Base 中声明为virtual
为了在派生类中达成覆盖重写, 以下条件需要被满足:

  • 基类函数必须是虚函数virtual
  • 基函数名和派生函数名必须相同 (析构函数除外)
  • 基函数和派生函数的参数类型必须相同
  • 基函数和派生函数的const修饰符必须相同
  • 基函数和派生函数的返回类型和异常规范必须兼容
  • 基函数和派生函数的引用限定符必须相同
C++11 开始, override 关键提供了明确告诉编译器我们想要覆盖重写函数的能力. 如果这种覆盖不成功, 即如果我们的代码忽略了上面提到的某些要求, 编译器将明确拒绝并告诉我们问题出在哪里.
因此, 这里我们倡议的准则是, 每当打算覆盖重写基类中的虚函数时, 用 override 关键字并让编译器帮我们检查重写是否奏效.
关于引用限定符, 我们将额外讲解一点知识. 这是为了区分对象(*this)是左值对象还是右值对象. 这不是很常见的用法, 但有时确实会出现. 例如:
class Widget {
public:
  using DataType = std::vector<double>;
  ...
  DataType& data() & {                // for lvalue Widgets, return lvalue
    return values;
  }
  
  DataType&& data() && {        // for rvalue Widgets, return rvalue
    return std::move(values);
  }
  ...
private:
  DataType values;
};

auto vals1 = w.data();                 // call lvalue overload, copy-construct vals1

auto vals2 = makeWidget().data();// call rvalue overload, move-construct vals2
<hr/>欢迎大家指出不足或错误, 进行提问和讨论.
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表