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表明當前函數必然是重載父類虛函數,而不是自定義聲明.

    • 可以避免重載錯誤,和上層改動,下游的繼承子類不清楚情況.

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