© FOTOGRIN/Shutterstock.com
作為一種面向對象的編程語言,C++ 經常依賴於繼承的實現。此功能允許您修改和重用類的屬性和其他特徵,並減少所需的代碼量。繼續閱讀以準確了解什麼是繼承以及您可以在 C++ 中使用的繼承類型。
什麼是繼承?
我們可以“繼承”某些特徵的方式很多從我們的父母那裡,在 C++ 中,類可以從另一個類繼承成員。這樣,其成員被繼承的類被定義為基類或父類,繼承這些特徵的類被稱為派生類、子類或子類。由於這允許重用父類的成員,因此不需要重新定義這些成員。因此,您可以節省實施不必要代碼的時間。
與友元函數和友元類有相似之處,因為它們允許函數和類訪問其他類的成員。但是,friend 允許訪問私有成員,而繼承則不允許。
C++ 中的繼承類型有哪些?
C++ 中有 5 種繼承類型。它們是:
單繼承多級繼承多繼承混合繼承分層繼承
讓我們逐一看看。
單繼承
最簡單的繼承方法是一個類繼承另一個類的成員。這可以用以下代碼顯示:
#include class BaseClass { public: int x; };類 DerivedClass: public BaseClass{ public: int y; }; int main() { DerivedClass obj; obj.x=10 obj.y=20 std::cout”基類成員變量x=”std::endl; std::cout”派生類成員變量 y=”obk.y std::endl;返回 0; }
在這裡,我們將基類定義為“BaseClass”,成員“x”具有公共訪問權限。派生類定義為“DerivedClass”,公開繼承自“BaseClass”。派生類本身有一個名為“y”的公共成員。我們創建了一個名為“DerivedClass obj”的派生類實例,並設置了 x 和 y 值。使用此對象,我們從父類訪問成員“x”,並將 x 和 y 值打印到控制台,如屏幕截圖所示。
示例中顯示的單一繼承。
©”TNGD”.com
Inheriting private members
值得注意的是,派生類可以繼承父類的所有成員,因為它們具有公共訪問權限。但是,如果成員聲明為私有,則不能直接繼承這些成員。解決此問題的方法是繼承作用於這些成員的某些功能。通過這種方式,您可以間接訪問這些成員。舉個例子:
class Base{ private: int a; public: Base(int a) a(a) {} int getA() const { return a; } };派生類:公共基地{公共:派生(int a):基地(A){}}; int main() { 派生 d(5); std::cout”派生對象的值:”d.getA() std::endl;返回 0; }
在這裡,我們將父類定義為“Base”,將派生類定義為“Derived”。父類的成員“a”是私有的,因此派生類不能直接訪問。但是,我們在基類中有一個構造函數,它接受整數參數“a”並設置私有成員“a”。派生類本身有一個構造函數,“Derived(int a): Base (a) {}”,它接受整數參數“a”並將其傳遞給基類的構造函數。因為繼承了“getA()”函數,所以實現了對父類成員“a”的間接訪問。
利用“main”函數,我們獲取了一個實例“d”派生類並用參數 5 定義它。在這個實例上調用“getA()”函數,並打印輸出。這顯示在屏幕截圖中。
如何繼承私有成員,如示例所示。
©”TNGD”.com
私有類與受保護類
現階段值得區分私有類和保護類。私有類成員只能由派生類間接訪問,而受保護類成員可以由派生類完全訪問。但是它們只能在這個類層次結構中訪問,而不能在它之外訪問(這將是公共訪問)。
僅方法繼承
這些示例還顯示了字段繼承,其中字段“a”已被繼承。但是你也可以有純方法繼承,其中一個方法用於定義類的行為。下面顯示了一個例子:
#inlude class Base { public: virtual void bar() { std::cout”Base::bar()”std::endl; } };派生類:public Base { public:virtual voide bar() { std::cout”Derived::bar()”std::endl; } }; int main() { Base* b=new Derived(); b->酒吧();//輸出”Derived::bar()”delete b;返回 0; }
和以前一樣,我們有一個父類“Base”和一個派生類“Derived”。 “Base”有一個虛方法“bar()”。這稱為虛擬,因為它在父類中沒有實現,並且可以被派生類覆蓋。如果在派生類定義中提供了“bar()”,則實現。我們可以看到在“main()”函數中創建了一個指針“b”,並用對象“Derived”進行了初始化。 “Derived::bar()”覆蓋了“Base::bar()”,因為它是一個虛函數。調用派生類中的實現,它打印輸出“Derived::bar()”,如屏幕截圖所示。
顯示僅方法繼承的示例。
©”TNGD”.com
多級繼承
在許多情況下,您可能希望從已經從父類派生的類創建派生類。這稱為多級繼承。就 C++ 中的繼承類型而言,這個是相當直觀的。一個這樣的例子是當您使用車輛類型時。在這種情況下,您可能有一個父類“Vehicles”,它定義了您正在使用的車輛(例如汽車和摩托車)通用的某些方法和參數。這些都可以是來自該父類的派生類,具有自己的特定屬性。但是由於您可能擁有這些類型的特定類型,因此您可以創建派生類,例如“PerformanceCar”,它們將具有自己適用的屬性。
我們可以使用以下代碼說明其工作原理:
#include #include class Vehicle { public: std::string 類型; std::字符串顏色; };類汽車:公共車輛{公共:std:: string模型;整數年; };類電動汽車:公共汽車{公共:int batteryCapacity; }; int main() { ElectricCar 特斯拉; tesla.type=”電動車”; tesla.color=”紅色”; tesla.model=”模型 S”;特斯拉.year=2021;特斯拉.電池容量=100; std::cout”Type:”tesla.type std::endl; std::cout“顏色:”tesla.color std::endl; std::cout“模型:”tesla.model std::endl; std::cout”年:”tesla.year std::endl; std::cout“電池容量:”tesla.batteryCapacity std::endl;返回 0; }
在這個例子中,我們有“Vehicle”基類、派生類“Car”和一個名為“ElectricCar”的進一步派生類。 “Vehicle”類有“type”和“color”成員,“Car”類有成員“model”和整型變量“year”,“ElectricCar”類有整型成員變量“batteryCapacity”。主函數創建“ElectricCar”類的一個實例,為其所有繼承的成員變量設置特定值。然後將這些變量打印到控制台。
示例中實現的多級繼承及其輸出。
©”TNGD”.com
多級繼承
就像我們可以派生類一樣從一個已經派生的類,我們可以有一個派生自多個基類的類。我們可以通過繼續我們的汽車類比來證明這一點:
#include #include class Vehicle { public: std::string type; std::字符串顏色; };類 ElectricEngine { 公共:int batteryCapacity; }; SportsCar 類 { 公共:int topSpeed; };類 ElectricSportsCar:公共車輛,公共 ElectricEngine,公共 SportsCar { public:std::string 模型;整數年; }; int main() { ElectricSportsCar 特斯拉; tesla.type=”電動車”; tesla.color=”紅色”; tesla.model=”敞篷跑車”;特斯拉.year=2022;特斯拉.電池容量=200;特斯拉.topSpeed=250; std::cout”Type:”tesla.type std::endl; std::cout“顏色:”tesla.color std::endl; std::cout“模型:”tesla.model std::endl; std::cout”年:”tesla.year std::endl; std::cout“電池容量:”tesla.batteryCapacity“kWh”std::endl; std::cout“最高速度:”tesla.topSpeed“mph”std::endl;返回 0; }
我們這裡有三個類,“Vehicle”、“ElectricEngine”和“SportsCar”。這些都是基類,它們的屬性被派生類“ElectricSportsCar”繼承。和以前一樣,每個父類都有自己的變量。創建“ElectricSportsCar”實例,為其屬性分配值,然後將這些值打印到控制台。
多重繼承的例子。
©”TNGD”.com
層次繼承
我們即將結束 C++ 中不同類型的繼承。這是情況有點微妙的地方。儘管多級繼承在技術上創建了層次結構,但這與所謂的層次繼承不同。如果您從一個父類創建多個派生類,這稱為層次繼承。當您需要從父類創建相關類,但每個類都有自己的屬性時,這很有用。下面的代碼顯示了這個例子。
class Vehicle { public: std::string type; std::字符串顏色; };類汽車:公共車輛{公共:std::字符串模型;整數年; };類卡車:公共車輛{公共:int容量; };
同樣,我們有“Vehicle”父類,“Car”和“Truck”類都是從它派生的。這兩個類都繼承了“type”和“color”變量,但也添加了自己的屬性。即,“汽車”類的“型號”和“年份”以及“卡車”類的“容量”。在第一個屏幕截圖中,我們可以看到使用“main()”函數實現的代碼,其中創建了每個類的實例並設置了它的屬性。第二個屏幕截圖顯示了控制台中的輸出。
在類中實現層次繼承。
©”TNGD”.com
上面示例的輸出。
©”TNGD”.com
混合繼承
當談到混合繼承時,情況會變得有點複雜。這就是 C++ 中不同類型的繼承在一個類層次結構中組合在一起的地方。雖然這可能會變得複雜,但有時對於您需要執行的操作來說是必要的。考慮以下情況:
#include #include class Vehicle { public: std::string type; std:: 字符串顏色; };引擎類 { 公共:int 馬力; };類汽車:公共車輛,公共引擎{公共:std:: string模型;整數年; };類電動汽車:公共汽車{公共:int batteryCapacity; };在 main() { ElectricCar 特斯拉; tesla.type=”電動車”; tesla.color=”紅色”; tesla.model=”模型 S”;特斯拉.horsepower=300;特斯拉.year=2021;特斯拉.電池容量=100; tesla.type=”電動車”; std::cout”Type:”tesla.type std::endl; std::cout“顏色:”tesla.color std::endl; std::cout “馬力:” tesla.horsepower std::endl; std::cout“模型:”tesla.model std::endl; std::cout”年:”tesla.year std::endl; std::cout“電池容量:”tesla.batteryCapacity std::endl;返回 0; }
和以前一樣,我們有“Vehicle”父類,還有“Engine”父類。我們有一個多重繼承的例子,其中“Car”類派生自“Vehicle”和“Engine”類。然後“ElectricCar”類派生自“Car”類,這是多級繼承的一個例子,因為這是一種更專業的汽車類型。因此,我們有一個正在發生混合繼承的場景。因此,混合繼承有助於簡化和理解複雜的關係,並使代碼更易於維護。
第一張圖片說明了代碼實現,我們在其中創建了一個實例“ElectricCar”類及其所有父類的屬性集。打印輸出顯示在第二張圖片中。
在類中實現混合繼承。
©”TNGD”.com
上面例子的輸出。
©”TNGD”.com
歧義注意事項
處理多個類時可能出現的一個非常普遍的問題是歧義問題。這是您在兩個或多個類中擁有相同成員變量或函數的地方。然後,編譯器可能會遇到錯誤,因為它無法決定將哪個成員用於您嘗試運行的操作。考慮以下代碼:
#include class A { public: void foo() {std::cout”A:foo()”std::endl;} }; B 類 { public: void foo() {std::cout”B::foo()”std::endl;} }; C類:公共A,公共B {公共:}; int main() { C c; c.foo();//編譯器錯誤:A 和 B 對 foo() 的不明確調用返回 0; }
在這裡,我們在“A”類和“B”類中都有一個名為“foo()”的函數。由於“C”類繼承自這兩個類,因此在編譯過程中會發生錯誤。這可以通過幾種不同的方式解決:
重命名父類或派生類中的衝突函數或變量以避免混淆。使用範圍解析運算符 (::) 指定包含所需成員函數的類。虛繼承的工作原理與前面提到的虛函數類似。這可以允許派生類從父類繼承,而無需複制這些父類共享的基類。通過使用專門的實現在派生類中重新定義函數來覆蓋衝突的函數。 說明了歧義錯誤。
©”TNGD”.com
總結
您可以使用 C++ 中的 5 種主要繼承類型,每種類型都有自己的特定用例。雖然單一繼承可能適用於相對簡單的操作,但在處理複雜的對象和關係時,其他類型(例如多重、多級、分層和混合繼承)可能更合適。這些有助於使代碼更直觀、更易於維護,以及更好地表示類之間的關係。
Inheritance in C++ Explained, With Examples FAQs(常見問題解答)
什麼是父類和派生類?
父類,也稱為基類,是繼承自的類。另一方面,派生類、子類或子類從父類繼承特性和屬性。
C++ 中的繼承是什麼?
繼承是一個使您能夠從父類或基類創建派生類的過程,派生類從父類繼承屬性和成員函數。這對於表示複雜的關係和減少重複代碼實現的需要很有用。
C++ 中有哪些不同類型的繼承?
有C++ 中的 5 種主要繼承類型——單繼承、多繼承、多級繼承、分層繼承和混合繼承。單類和多類分別是指從一個或多個基類派生的單個類。多級繼承是指一個類是從派生類派生的。分層繼承是指從一個基類派生多個類,而混合繼承是指混合使用這些其他類型。
如何在 C++ 中實現繼承?
要使類繼承自父類,您可以使用冒號 (:),後跟訪問說明符(在本例中為 public 或 protected)和基類名稱。
什麼是公共成員、受保護成員和私有成員?
公共成員在程序中的任何地方都是完全可見和可訪問的,並且可以被類內外的任何函數訪問.受保護的成員可以被派生類訪問,因此可以被繼承。私有成員不能被類外的任何函數訪問,並且對派生類不可見。但是,如果作用於私有成員的公共函數被繼承,私有成員可以是間接的。
公共、私有和受保護繼承之間有什麼區別?
公共繼承是基類的所有公共成員成為派生類的公共成員的地方,保護成員和私有成員也是如此。受保護的繼承是公共成員和受保護成員都被繼承,但私有成員仍然不可訪問。私有繼承意味著公共成員和受保護成員成為派生類的私有成員,而且私有成員一如既往地保持不可見。
如何解決繼承中的歧義?
您可以通過使用範圍解析生成器、使用虛擬繼承或通過重命名或重新定義衝突函數來解決歧義。