Item 12: Declare overriding functions override.

Item 12: Declare overriding functions override.

Effective Modern C++ Item 12 的学习和解读。

面向对象的 C++ 主要特性是类、继承、虚函数,而这些特性的基础是继承类中重写基类的虚函数。重写(overriding)和重载(overloading)看着比较相似,但其实完全不同。重写的一个例子:

class Base {
public:
  virtual void doWork(); // base class virtual function
  ...
};

class Derived: public Base {
public:
  virtual void doWork();  // overrides Base::doWork ("virtual" is optional here)
  ...
};

std::unique_ptr<Base> upb = std::make_unique<Derived>();
...
upb->doWork(); // call doWork through base class ptr; derived class function is invoked

重写需要满足的条件:

  • 基类的重写函数必须是虚函数。
  • 基类和继承类的重写函数的函数名必须相同。
  • 基类和继承类的重写函数的参数类型必须相同。
  • 基类和继承类的重写函数的常量属性必须相同。
  • 基类和继承类的重写的函数的返回值类型和异常规格说明要兼容。

除了 C++98 的这些限制条件,C++11 还增加了一条:

  • 基类和继承类的重写函数的引用修饰符必须相同。

引用修饰符包括左值和右值两种,左值引用成员函数可以被 *this 为左值调用,右值引用成员函数可以被 *this 为右值调用。看一个例子:

#include <iostream>

class Widget {
public:
  void doWork() & {   // this version of doWork applies only when *this is an lvalue
    std::cout << "doWork() &" << std::endl;
  }
  void doWork() && {  // this version of doWork applies only when *this is an rvalue
    std::cout << "doWork() &&" << std::endl;
  }
};

Widget makeWidget()  { // factory function (returns rvalue)
  return Widget();
}

int main() {
  Widget w;
  w.doWork();
  makeWidget().doWork();
}

// 打印信息
doWork() &
doWork() &&

这里,w 是个左值,所以调用的是 doWork() & 函数,而 makeWidget() 返回的是一个右值,所以调用的是 doWork() && 函数。

重写的条件是非常严格的,细小的差错将会导致完全不同的结果。看个例子:

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();  // 缺少 const
  virtual void mf2(unsigned int x); // 参数类型不同
  virtual void mf3() &&;  // 引用修饰符不同
  void mf4() const;  // 基类没有加 virtual 修饰
};

以上代码,有的编译器会给出警告,有的编译器给的警告不全,还有的编译器不会给警告。所以保险的做法是自己将重写函数标记为 override,这样的话,不符合重写条件的话,编译器一定会报错。

所以,当你在继承类中要重写函数的话,加上 override 吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值