主要內容
好處
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); }
int
和bool
參數不一樣,是兩個函數.
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
表明當前函數必然是重載父類虛函數,而不是自定義聲明.可以避免重載錯誤,和上層改動,下游的繼承子類不清楚情況.