• C++11: final & override


    引言

    final和override都是C++11新引入的关键字,由于两关键字都于继承控制相关,所以我们称final和override为继承控制关键字,需要说明的是final 可作用于类,亦可作用于成员函数,override则只能作用于虚函数。那C++11引入final和override两关键字是为了解决什么问题呢?

    缘由

    C++11之前,由于C++没有一个强制机制限制基类和派生类的继承和重写关系,我们经常会遇到这两类问题。一叫无意重写,另一类叫“假”继承。

    无意重写

    class Window
    {
    public:
        virtual void Draw();
    };
    
    class View : public Window 
    {
    public:
        void Draw();
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    此例中 ,派生类View本意是声明一个归属自己的成员函数,但是不小心重写了父类的Draw。最终导致行为非预期。

    “假”继承

    class Window
    {
    public:
        virtual void Draw() const;
    };
    
    class View : public Window 
    {
    public:
        virtual void Draw();
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    作者本意是让View中的成员函数Draw重写基类Window成员函数Draw,但是由于Draw函数签名的不一致,最终导致重写失败。也是我们所说的“假”继承,“假”继承也是非作者所望。

    函数签名,一般包括 :

    • 函数名称,
    • 参数列表,
    • 以及修饰符(如:const)

    为了解决无意重写和“假”继承问题,C++11才引入关键字override和final关键字。override负责解决“假”继承问题,final负责解决无意继承问题。

    final & override

    final的引入是为了禁止类的进一步派生以及虚函数的进一步重写。override则是为了保证派生类中重载的虚函数与父类具有相同的函数签名。

    override

    class Window
    {
    public:
        virtual void Draw() const;
    };
    
    class View : public Window 
    {
    public:
        virtual void Draw() override;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在派生类需要重写的函数声明后面添加override。派生类声明的重写函数与基类具有不同的函数签名,编译器在编译时会提示编译错误。这样我们就会有机会修正自己的编码实现,从而解决“假”继承问题。

    final

    final可以阻止函数重写,亦可禁止子类派生。在派生类的声明时添加final可禁止子类派生,在虚函数声明时添加final可禁止派生类重写。

    禁止派生

    class Window final
    {
    public:
        virtual void Draw() const;
    };
    
    class View: public Window 
    {
    public:
        virtual void Draw() override;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    声明Window为final,这样View声明继承Window,编译器在编译时会提示错误。

    禁止继承

    class Window
    {
    public:
        virtual void Draw() const final;
    };
    
    class View: public Window 
    {
    public:
        virtual void Draw() override;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    声明基类Window中的成员函数Draw为final,那么在子类View中如果重写了Draw,编译器在编译时也会提示编译错误。

    总结

    本文从C++98&C++03标准中存在的问题入手,深入浅出的介绍了C++11引入final&override的原因及其所解决的问题。

  • 相关阅读:
    深度解读:金融企业容器云平台存储如何选型
    代码随想录训练营第六十天| 84.柱状图中最大的矩形
    Kafka消息分区&producer拦截器&无消息丢失(八)
    rgb转hsl,红绿蓝转色调饱和度亮度(颜色转换,c#)
    ElasticSearch集群部署
    智能合约平台开发指南
    radis相关面试题
    学习react,复制一个civitai(C站)-更新3
    js控制图片在可视区域才展示,图片懒加载
    【uni-app系列】uni-ui扩展组件和uViewUI的安装使用
  • 原文地址:https://blog.csdn.net/liuguang841118/article/details/127718182