一、繼承的基本概念
繼承是面向對象程序設計的基本特徵之一。在C++語言中,繼承允許我們定義一個新的類,這個新類繼承已有的類的屬性和行為,從而可以重複使用已有類的代碼,避免代碼冗餘。
在C++中,通過在類定義中使用「:」符號,來指定一個類從另一個類繼承而來。被繼承的類稱為基類,新定義的類稱為派生類。派生類可以繼承基類的公有成員、保護成員和私有成員,但只有公有成員能夠被外部程序訪問。
class BaseClass { public: void publicFunc() { //公有函數 std::cout << "BaseClass 的 publicFunc() 函數" << std::endl; } protected: void protectedFunc() { // 保護函數 std::cout << "BaseClass 的 protectedFunc() 函數" << std::endl; } private: void privateFunc() { // 私有函數 std::cout << "BaseClass 的 privateFunc() 函數" << std::endl; } }; class DerivedClass : public BaseClass { public: void callPublicFunc() { publicFunc(); // 從基類繼承的公有函數 } void callProtectedFunc() { protectedFunc(); // 從基類繼承的保護函數 } //void callPrivateFunc() { privateFunc(); }; 該語句會編譯錯誤 }; int main() { DerivedClass obj; obj.callPublicFunc(); //調用從基類繼承而來的公有成員函數 obj.callProtectedFunc(); //調用從基類繼承而來的保護成員函數 //obj.callPrivateFunc(); //編譯錯誤,私有成員函數不能被訪問 return 0; }
二、繼承類型
在C++中,繼承被分為三類:公有繼承、保護繼承和私有繼承。
1.公有繼承
公有繼承是最常用的繼承方式,它指定派生類能夠繼承基類的公有成員和保護成員。在公有繼承中,基類的公有成員和保護成員在派生類中的訪問許可權不變。
class BaseClass { public: void publicFunc() { std::cout << "BaseClass 的公有函數" << std::endl; } protected: void protectedFunc() { std::cout << "BaseClass 的保護函數" << std::endl; } }; class DerivedClass : public BaseClass { //從基類繼承而來的公有成員和保護成員在DerivedClass中的訪問許可權不變 }; int main() { DerivedClass obj; obj.publicFunc(); //從基類繼承而來的公有成員函數可以在外部程序中被訪問 //obj.protectedFunc(); 非法,派生類外不能訪問基類的保護成員 return 0; }
2.保護繼承
保護繼承與公有繼承類似,不同之處在於基類的公有成員和保護成員在派生類中都成為保護成員,在派生類外部不能訪問。只有派生類的成員函數或友元函數能夠訪問它們。
class BaseClass { public: void publicFunc() { std::cout << "BaseClass 的公有函數" << std::endl; } protected: void protectedFunc() { std::cout << "BaseClass 的保護函數" << std::endl; } }; class DerivedClass : protected BaseClass { //從基類繼承而來的公有成員和保護成員在DerivedClass中成為保護成員,其他程序不能訪問 public: void callProtectedFunc() { protectedFunc(); //從基類繼承而來的保護函數可以在派生類中被訪問 } }; int main() { DerivedClass obj; //obj.publicFunc(); 非法,從基類繼承而來的公有成員在派生類外部不能訪問 //obj.protectedFunc(); 非法,從基類繼承而來的保護成員在派生類外部不能訪問 obj.callProtectedFunc(); //從基類繼承而來的保護函數可以在派生類中被訪問 return 0; }
3.私有繼承
私有繼承意味著基類的公有和保護成員在派生類中均成為私有成員,只有派生類的成員函數或友元函數能夠訪問它們。私有繼承不會帶來新的介面。
class BaseClass { public: void publicFunc() { std::cout << "BaseClass 的公有函數" << std::endl; } protected: void protectedFunc() { std::cout << "BaseClass 的保護函數" << std::endl; } }; class DerivedClass : private BaseClass { //從基類繼承而來的公有成員和保護成員在DerivedClass中均為私有成員 public: void callProtectedFunc() { protectedFunc(); //從基類繼承而來的保護函數可以在派生類中被訪問 } }; int main() { DerivedClass obj; //obj.publicFunc(); 非法,從基類繼承而來的公有成員在派生類外部不能訪問 //obj.protectedFunc(); 非法,從基類繼承而來的保護成員在派生類外部不能訪問 obj.callProtectedFunc(); //從基類繼承而來的保護函數可以在派生類中被訪問 return 0; }
三、構造函數和析構函數中的繼承
在進行繼承時,基類的構造函數和析構函數會被自動調用。
在構造派生類的對象時,首先會調用基類的默認構造函數,然後調用派生類的構造函數。當然,也可以在派生類的構造函數中顯式調用基類的構造函數。考慮以下代碼:
class BaseClass { public: BaseClass() { //基類的默認構造函數 std::cout << "BaseClass 的構造函數" << std::endl; } ~BaseClass() { //基類的析構函數 std::cout << "BaseClass 的析構函數" << std::endl; } }; class DerivedClass : public BaseClass { public: DerivedClass() { //派生類的構造函數 std::cout << "DerivedClass 的構造函數" << std::endl; } ~DerivedClass() { //派生類的析構函數 std::cout << "DerivedClass 的析構函數" << std::endl; } }; int main() { DerivedClass obj; //創建一個派生類的對象 return 0; }
執行上述代碼,將輸出以下結果:
BaseClass 的構造函數 DerivedClass 的構造函數 DerivedClass 的析構函數 BaseClass 的析構函數
在析構派生類的對象時,先調用派生類的析構函數,然後調用基類的析構函數。同樣,也可以在派生類的析構函數中顯式調用基類的析構函數。
四、虛函數和多態
虛函數是C++用於實現多態的重要機制。在基類中聲明一個虛函數,派生類可以根據其需求重新定義這個虛函數,以實現多態性。在調用虛函數時,函數的實際調用取決於對象的類型,而不是指向該對象的指針或引用類型。例如:
class BaseClass { public: virtual void virtualFunc() { std::cout << "BaseClass 的虛函數" << std::endl; } }; class DerivedClass : public BaseClass { public: void virtualFunc() { //重定義基類的虛函數 std::cout << "DerivedClass 的虛函數" << std::endl; } }; int main() { DerivedClass obj; //創建一個派生類的對象 BaseClass& ref = obj; //使用基類的引用來引用派生類的對象 ref.virtualFunc(); //調用「引用的對象」的虛函數 return 0; }
以上代碼中,我們聲明了一個基類和一個派生類,基類中的虛函數被派生類重定義,使得它們的實現不同。在main函數中,創建了一個派生類對象,並用基類的引用來引用該對象,最後調用了該對象的虛函數。由於虛函數是根據對象類型而不是引用類型確定的,因此程序將調用派生類的虛函數,輸出以下內容:
DerivedClass 的虛函數
五、抽象類
抽象類是具有至少一個純虛函數的類,不能直接實例化,只能作為其他類的基類使用。純虛函數沒有函數體,只有函數原型。在基類中聲明純虛函數後,在派生類中必須定義該函數,否則將編譯錯誤。
class AbstractClass { //抽象類 public: virtual void pureVirtualFunc() = 0; //純虛函數 }; class DerivedClass : public AbstractClass { public: void pureVirtualFunc() { std::cout << "DerivedClass 實現了純虛函數 pureVirtualFunc()" << std::endl; } }; int main() { //AbstractClass obj; 非法,抽象類不能直接實例化 DerivedClass obj; //創建一個派生類的對象 AbstractClass& ref = obj; //使用基類的引用來引用派生類的對象 ref.pureVirtualFunc(); //調用「引用的對象」的純虛函數 return 0; }
在以上示例中,AbstractClass 是一個抽象類,定義了一個純虛函數。派生類DerivedClass 定義了純虛函數 pureVirtualFunc() 的實現,使得該派生類不再是抽象類。最後,創建了一個DerivedClass 對象,並用基類的引用來引用它,並調用了該對象的純虛函數。
六、總結
在C++中,繼承是構建類層級結構的關鍵技術之一。通過繼承,我們可以重用已有的類的代碼,提高程序的可維護性和可擴展性。C++中的繼承有三種類型:公有繼承、保護繼承和私有繼承。
C++中的構造函數和析構函數在進行繼承時,會自動調用。虛函數和多態則是C++實現動態多態的重要機制。抽象類不能直接實例化,必須作為其他類的基類使用。
了解和掌握C++中的繼承及相關特性,有助於我們構建更加複雜的類層級結構,提高
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/256550.html