Item12 Declare overriding function override

   在C++面向对象的世界里面主要是围绕着类、继承和虚函数,而在这个世界里面虚函数的实现就是靠派生类重写基类的虚函数,但是这很容易出错, 这是符合墨菲定律的。因为重写听起来像重载,然而这两个其实是不相关的。

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

class Devired : public Base {
  public:
    virtual void doWork();
};

重写需要满足一定的要求:

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

除了上面这些要求外,C++11中又添加了新的要求。

  • 基类和派生类要重写的函数的引用标识符必须相同

   引用标识符? 我相信很多人不是太清楚这个C++11中引入的新特性,它其实和成员函数的const修饰符差不多,只能用于修饰成员函数,引用标识符有两个,一个是 &,用这个修饰的成员函数只允许被*this是左值来调用。另外一个是&&,值允许被*this是右值来调用。

class Widget {
 public:
  void doWork() & {
    std::cout << "I am & doWork" << std::endl;
  }

  void doWork() && {
    std::cout << "I am && doWork" << std::endl;
  }
};

Widget makeWidget() {
  return Widget();
}

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

   上面的程序中,w是个左值,所以调用的是输出I am & doWorkdoWork函数,而makeWidget返回的是一个右值的Widget,所有调用的是被&&修饰的doWork函数。

   上面这些都是重写基类虚函数的要求,可想而知一点点小错误都会导致很大的差异,如果代码中进行了错误的重写这是很难察觉的,毕竟错误的重写从语法角度来说也是正确的,只是语意变了,下面是一些典型的重写错误。

class Basse {
 public:
  virtual void mf1() const;
  virtual void mf2(int x);
  virtual void mf3()&;
  void mf4() const;
};

class Dervired : public Base {
 public:
  virtual void mf1();               // 却少const
  virtual void mf2(unsigned int x);  // 参数类型不同
  virtual void mf3() &&;            // 引用标识符不同
  void mf4() const;                 // 基类对应函数不是虚函数
};

   看到这里你应该明白了,重写真的容易出错了吧,智能一点的编译器可能会提示我们,但这不是绝对的,要想从根本上解决这个问题还的要从语言本身上下功夫,C++11中引入的override关键字就是起到这个作用,用于修饰派生类,表明这是一个重写函数,那么此时编译器会进行函数签名的校验,如果发现不同就会直接报错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值