C++ 11 override , 虚函数重载一定要用

  • 主要内容

    • 好处

      • C++11提供override关键字用于保障虚函数重载的正确性.

    • 虚函数重载

      • 和父类的虚函数声明一毛一样.

    • 如何一样

      • 虚函数才能重载.

      • 函数名一样.(析构除外).

      • 入参一样.

      • 函数修饰一样.

      • 返回值和异常处理兼容.

  • 非虚函数

    • 案例

      #include <iostream>
      #include <memory>
      class A {
      public:
         void show(int a){
             std::cout <<  __FUNCTION__ << " : " << __LINE__ << std::endl;
         }
      };
      
      class B:public A {
      public:
         void show(int a) {
             std::cout <<  __FUNCTION__ << " : " << __LINE__ << std::endl;
         }
      };
      
      int main() {
         A *a = new B();
         a->show(1);
      }
      
      • 输出

      show : 6
      [Finished in 651ms]
      
  • 函数名一致

    • 析构

      #include <iostream>
      #include <memory>
      class A {
      public:
         virtual ~A() {
             std::cout <<  __FUNCTION__ << " : " << __LINE__ << std::endl;
         }
      };
      
      class B:public A {
      public:
         ~B() {
             std::cout <<  __FUNCTION__ << " : " << __LINE__ << std::endl;
         }
      };
      
      int main() {
         A *a = new B();
         delete a;
      }
      
      • 输出

      ~B : 13
      ~A : 6
      [Finished in 502ms]
      
    • 显式调用

      #include <iostream>
      #include <memory>
      class A {
      public:
         virtual ~A() {
             std::cout <<  __FUNCTION__ << " : " << __LINE__ << std::endl;
         }
      };
      
      class B:public A {
      public:
         ~B() {
             std::cout <<  __FUNCTION__ << " : " << __LINE__ << std::endl;
         }
      };
      
      int main() {
         A *a = new B();
         a->~A();
      }
      
      • 输出

      ~B : 13
      ~A : 6
      [Finished in 506ms]
      
  • 入参不一致

    • 案例

      #include <iostream>
      #include <memory>
      class A {
      public:
         virtual void show(int a){
             std::cout <<  __FUNCTION__ << " : " << __LINE__ << std::endl;
         }
      };
      
      class B:public A {
      public:
         virtual void show(bool a) {
             std::cout <<  __FUNCTION__ << " : " << __LINE__ << std::endl;
         }
      };
      
      int main() {
         A *a = new B();
         a->show(1);
      }
      
      • intbool参数不一样,是两个函数.

      • 1的匹配show(int)的准确度更高.

      show : 6
      [Finished in 477ms]
      
    • 小结

      • 函数都不是一个函数,更别说重载了.

      • 不是一个函数,就相当于新声明了一个虚函数.

  • 修饰不一致

    • 案例

      #include <iostream>
      #include <memory>
      class A {
      public:
         virtual void show(int a) const {
             std::cout <<  __FUNCTION__ << " : " << __LINE__ << std::endl;
         }
      };
      
      class B:public A {
      public:
         virtual void show(int a) {
             std::cout <<  __FUNCTION__ << " : " << __LINE__ << std::endl;
         }
      };
      
      int main() {
         A *a = new B();
         a->show(1);
      }
      
      • 修饰不一致,B的实现没有const.所以是两个函数.

      show : 6
      [Finished in 808ms]
      
      • 两个函数则调用当前类型匹配度最高的.

    • 小结

      • 修饰不一样,函数名也不再一样.所以重载的也就不一样.

  • override解决的问题

    • 核心功能

      • 检测父类中是否却有如此声明的虚函数.

      • 即编译器帮忙检测是否正确的继承了函数.而不是说子类重载了个寂寞.

    • C++11

      • 对函数进行修饰,可以根据不同的上下文进行不同的操作.

      • 能够更加精确的控制.和更高的利用率.

      • 但是带来了重载的麻烦。

    • 改动

      • 如果基类进行了相关的改动.

      • 那么子类声明了override的都会在编译阶段就发现了改动的问题.

    • override生效

      • 尽在函数末尾生效,函数名或变量不会检测,或者是相关语义.

  • final

    • 禁止重载

      • 表示当前类的某个虚函数不能被重载.

    • 案例

      #include <iostream>
      #include <memory>
      class A {
      public:
         virtual void show(int a) const final {
             std::cout <<  __FUNCTION__ << " : " << __LINE__ << std::endl;
         }
      };
      
      class B:public A {
      public:
         virtual void show(int a) const override {
             std::cout <<  __FUNCTION__ << " : " << __LINE__ << std::endl;
         }
      };
      
      int main() {
         A *a = new B();
         a->show(1);
      }
      
      • B想重载父类的,但是父类不允许重载. 则编译报错.

      D:\codes\cfile\Test\test.cpp:12:18: error: virtual function 'virtual void B::show(int) const' overriding final function
          virtual void show(int a) const override {
                       ^~~~
      D:\codes\cfile\Test\test.cpp:5:18: note: overridden function is 'virtual void A::show(int) const'
          virtual void show(int a) const final {
                       ^~~~
      [Finished in 371ms]
      
      • 一般适用于叶子节点.

  • 符号修饰的函数场景

    • 说明

      • 对应类型调用对应的函数.
      • 比如左值右值就有天差地别.
    • []

      • 一般都是返回左值.

      • 但是当一个右值调用的时候也返回左值,就会出现引用悬空.

      • 即可能出现bug.

    • 语义

      • &是一个普通变量.
      • &&是一个不能取地址的,没有名字不能被引用的.

      • 虽然入参是右值,但是在调用函数内部,其变成了左值,因为可以放在等号左边,也可以取地址. 只是一个&&类型的变量而已.

    • 消亡

      • 语义上会立即释放.可以处于节约自由操作其资源.
  • 返回值和异常兼容

    • 略,还是需要严格一致. 没有看懂.

  • 总结

    • override表明当前函数必然是重载父类虚函数,而不是自定义声明.

    • 可以避免重载错误,和上层改动,下游的继承子类不清楚情况.

  • 發表評論
    所有評論
    還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
    相關文章