C++11新特性之六:override和final
struct B1 final { };
struct D1 : B1 { }; // 錯(cuò)誤!不能從 final 類繼承!
上面的代碼是錯(cuò)誤的,因?yàn)?D1 試圖繼承 B1,而 B1 則聲明為 final。很像 Java,不是嗎?當(dāng)然!還有另外的用法:struct B2
{
virtual void f() final {} // final 函數(shù)
};
struct D2 : B2
{
virtual void f() {} // 錯(cuò)誤!
};
這段代碼又會(huì)出錯(cuò),因?yàn)镈2::f重寫了B2::f,但是B2::f卻被聲明為 final 的!
我總覺得 C++中虛函數(shù)的設(shè)計(jì)很差勁,因?yàn)闀r(shí)至今日仍然沒有一個(gè)強(qiáng)制的機(jī)制來標(biāo)識(shí)虛函數(shù)會(huì)在派生類里被改寫。vitual關(guān)鍵字是可選的,這使得閱讀代碼變得很費(fèi)勁。因?yàn)榭赡苄枰匪莸嚼^承體系的源頭才能確定某個(gè)方法是否是虛函數(shù)。為了增加可讀性,我總是在派生類里也寫上virtual關(guān)鍵字,并且也鼓勵(lì)大家都這么做。即使這樣,仍然會(huì)產(chǎn)生一些微妙的錯(cuò)誤。
下面再看另外一段代碼:
struct B3
{
virtual void f() {}
};
struct D3 : B3
{
void f() {}
};
開發(fā) D3 的程序員真的想重寫B(tài)3::f函數(shù)嗎?還是說,他只是不小心寫了個(gè)與父類同名的函數(shù),卻在不經(jīng)意間導(dǎo)致了覆蓋?為了避免這種錯(cuò)誤,C++ 11 引入了override關(guān)鍵字(多么像 C# ?。。?。于是,我們會(huì)發(fā)現(xiàn),下面的一段代碼是會(huì)出錯(cuò)的:struct B4
{
virtual void g(int) {}
};
struct D4 : B4
{
virtual void g(int) override {} // OK
virtual void g(double) override {} // Error
};
多虧了override關(guān)鍵字,我們可以讓編譯器幫我們檢測到這個(gè)很難發(fā)現(xiàn)的程序錯(cuò)誤。這段代碼的錯(cuò)誤在于,override關(guān)鍵字表明,g(double)雖然想要進(jìn)行override的操作,但實(shí)際父類并沒有這么個(gè)函數(shù)。值得注意的是,這些并不是一些語法糖,而是能確確實(shí)實(shí)地避免很多程序錯(cuò)誤,并且暗示編譯器可以作出一些優(yōu)化。調(diào)用標(biāo)記了final的virtual函數(shù),例如上面的B2::f,GNU C++ 前端會(huì)識(shí)別出,這個(gè)函數(shù)不能被覆蓋,因此會(huì)將其從類的虛表中刪除。而標(biāo)記為final的類,例如上面的 B1,編譯器則根本不會(huì)生成虛表。這樣的代碼顯然更有效率。
https://www.devbean.net/2012/05/cpp11-override-final/