Effective Modern C++ Item 12 为意在改写的函数添加override声明

C++ 中虚函数override动作,从而使得基类接口调用派生类函数成为了可能,而这个override动作工作起来,需要满足如下要求:

  • 基类中函数必须是虚函数。

  • 基类和派生类中的函数名字必须完全相同(析构函数除外)。

  • 基类和派生类中的函数形参型别必须完全相同。

  • 基类和派生类中的函数常量性必须完全相同。

  • 基类和派生类中的函数返回值和异常规格必须兼容。

  • 基类和派生类中的函数引用饰词必须完全相同。(C++11以后,含11要求)

函数引用饰词这个语言特性以下做讲解:

class Widget {
public:
    void doWork() &;    //这个版本的doWork仅在*this是左值时候调用
    void doWork() &&;   //这个版本的doWork仅在*this是右值时候调用
};

Widget makewidget();    //工厂函数(返回右值)
Widget w;               //普通对象(左值)
...
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();
    virtual void mf2(unsigned int x);
    virtual void mf3() &&;
    void mf4() const;
}

那么区别在于:

  • Base 中的mf1是声明为const的,但是在Derived中的没有。
  • Base 中的mf2的形参型别是int,而Derived中的则是unsigned int。
  • Base 中的mf3带有左值引用饰词,而Derived中的带有右值引用饰词。
  • Base 中的mf4未声明为虚函数。

实际上上述情况一个都无法完成改写,更有甚者,编译器完全不会报告任何错误信息,这一点是极为可怕的,容易埋下祸根。而C++11开始提供了一种显示标记的方式让编译器检查改写是否成功。代码如下:

class Derived : public Base {
public:
    virtual void mf1() override;
    virtual void mf2(unsigned int x) override;
    virtual void mf3() && override;
    void mf4() const override;
}

一旦这么写后,编译器会强制检查,所标记函数必须能够改写基类对应接口,否则则会进行报错。

override的好处不仅仅在于强制让编译器检查改写,还可以在打算更改基类虚函数签名的时候,能够通过编译器的报错衡量波及范围。

需要强调的是,虽然override是个关键字,但是仅仅在特定语境下保留。对于已经将override作为一个变量或者一个函数名的时候,依旧不受影响。

题外话,引用饰词

这里写个对于引用饰词的使用场景:

class Widget {
public:
    using DataType = std::vector<double>;
    ...
    DataType& data() &          // 对于左值Widget型别,返回左值
    {return values;}

    DataType data() &&          // 对于右值Widget型别,返回右值
    {return std::move(values);}
}

// 对于以下调用能够高效进行

Widget w;
...
auto vals1 = w.data();
auto vals2 = makeWidget().data();

如果没有引用饰词,那么对于右值版本会将临时对象中的std::vector进行复制到vals2中。而显然对于vector这种型别来说,移动操作一般比复制操作开销要小。

要点速记
1. 为意在改写的函数添加override声明。
2. 成员函数引用饰词使得对于左值和右值对象可以处理可以区分开。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值