EMCPP条款12:为意在改写的函数添加override声明

YiQi 管理员

正是虚函数改写,使得通过基类接口调用派生类函数成为了可能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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)

};
// create base class pointer to derived class object;
std::unique_ptr<Base> upb = std::make_unique<Derived>();
// see Item 21 for info on std::make_unique

// call doWork through base class ptr; derived class function is invoked
upb->doWork();

而如果要这个改写动作真的发生,有一系列要求必须满足:

  • 基类中的函数必须是虚函数。
  • 基类和派生类中的函数名字必须完全相同(析构函数例外)
  • 基类和派生类中的函数形参型别必须完全相同 。
  • 基类和派生类中的函数常最性 (constness) 必须完全相同。
  • 基类和派生类中的函数返回值和异常规格必须兼容。
    而除了这些限制,也就是 C++98 给出的限制, C++11 又加了一条:
    • 基类和派生类中的函数引用饰词 (reference qualifier) 必须完全相同。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class Widget {
    public:

    void doWork() &; // this version of doWork applies only when *this is an lvalue

    void doWork() &&; // this version of doWork applies only when *this is an rvalue
    };

    Widget makeWidget(); // factory function (returns rvalue)
    Widget w; // normal object (an lvalue)

    w.doWork(); // calls Widget::doWork for lvalues (i.e., Widget::doWork &)

    makeWidget().doWork(); // calls Widget::doWork for rvalues (i.e., Widget::doWork &&)
    由于对于声明派生类中的改写,保证正确性很重要,而出错又很容易,C++11 提供了一种方法来显式地标明派生类中的函数是为了改写基类版本: 为其加上 override 声明。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Base {
public:
virtual void mf1() const;
virtual void mf2(int x);
virtual void mf3() &;
virtual void mf4() const;
};
class Derived: public Base {
public:
virtual void mf1() const override;
virtual void mf2(int x) override;
virtual void mf3() & override;
void mf4() const override; // adding "virtual" is OK but not necessary
};

要点速记

  • 为意在改写的函数添加 override 声明。
  • 成员函数引用饰词使得对于左值和右值对象 (*this) 的处理能够区分开来。
此页目录
EMCPP条款12:为意在改写的函数添加override声明