在C++中,成員函數的重載、覆蓋與隱藏是很容易混淆的概念,必定要搞清楚他們之間的關係與差異。html
一、成員函數重載的特性ios
(1)相同的範圍(即在同一個類中)。也就是意味着基類與派生類之間的成員函數不存在重載的關係;函數
(2)成員函數名字相同,參數不一樣;spa
(3)virtual關鍵字無關緊要。code
二、覆蓋htm
覆蓋是指派生類函數覆蓋基類函數,特徵是:對象
(1)不一樣的範圍(分別位於派生類與基類中);blog
(2)函數的名字相同,參數也相同;get
(3)基類函數必需要有virtual關鍵字修飾。io
三、隱藏
這裏的「隱藏」指的是派生類函數屏蔽了基類中與其同名的成員函數,須要與上面的兩個概念區別開來:
(1)若是派生類的函數與基類的函數同名,可是參數不一樣,此時不管基類函數是否有virtual關鍵字,基類函數
都將被「隱藏」。
(2)若是派生類函數與基類函數同名,而且參數也相同,可是基類函數沒有virtual關鍵字修飾,那麼此時
基類函數將被「隱藏」。
須要注意的地方:隱藏只是致使派生類實例化的對象沒法直接調用被隱藏的基類的成員函數,那麼在這種狀況
下,覆蓋的函數其實也是不能被調用的,其實能夠理解爲覆蓋自己也是一種隱藏,關鍵看咱們怎麼去調用
成員函數,若是是經過虛函數表的方式去調用那麼就出現覆蓋的特性。
固然,無論是隱藏仍是覆蓋,在成員函數內部仍是能夠調用的,例如:
#include <iostream> class CBassClass { public: virtual void FunC1(void) { std::cout << "CBassClass FunC1(void)" << std::endl; } virtual void FunC2(void) { std::cout << "CBassClass FunC2(void)" << std::endl; } virtual void FunC3(void) { std::cout << "CBassClass FunC3(void)" << std::endl; } }; class DClass :public CBassClass { public: virtual void FunC2(void) { std::cout << "DClass FunC2(void)" << std::endl; CBassClass::FunC2(); // 調用基類的成員函數 } virtual void FunC3(void) { std::cout << "DClass FunC3(void)" << std::endl; } virtual void FunC4(void) { std::cout << "DClass FunC4(void)" << std::endl; } virtual void FunC5(void) { std::cout << "DClass FunC5(void)" << std::endl; } };
這三個關係是很是容易混淆的,必定要注意他們之間的區別、不一樣之處。
參考博文:http://www.cnblogs.com/qlee/archive/2011/07/04/2097055.html