C++中繼承的概念和意義
在C++中,類與類之間的關係有組合與繼承兩種,以生活中的例子來舉例,組合就好比電腦這個類由主機板、CPU、記憶體、硬碟等這些類組成的,屬於整體與部分的關係,如下圖:
而繼承則好比電腦與蘋果電腦、戴爾電腦之間的關係,也叫父子關係,電腦為父類,蘋果電腦與戴爾電腦為子類,如下:
先來討論類的組合關係:
- 將其他類的物件作為當前類的成員使用
- 成員物件與當前類的物件生命週期相同
- 成員物件在用法上與普通物件完全一致
下邊來看一段程式碼:
#include <iostream> #include <string> using namespace std; class CPU { public: void fun() { cout << "I'm CPU" << endl; } }; class Disk { public: void fun() { cout << "I'm Disk" << endl; } }; class Computer { public: CPU m_cpu; //以CPU類的一個物件作為Computer類的成員變數 Disk m_disk; //以Disk類的一個物件作為Computer類的成員變數 void fun() { cout << "I'm Computer" << endl; } }; int main() { Computer computer; computer.fun(); computer.m_cpu.fun(); //呼叫CPU物件成員的fun() computer.m_disk.fun(); //呼叫Disk物件成員的fun() system("pause"); }
編譯輸出如下:
可以看到,使用成員物件與使用普通物件的方法是一致的,僅僅是多了巢狀而已,也可以在成員物件所在的類中再加入成員物件,好比CPU這個類中又有電阻電容這些類物件一樣,可以層層巢狀。
類的組合關係比較簡單,下邊來看看類的繼承關係
- 被繼承的類叫父類(或基類),繼承後的類叫子類(或派生類),如電腦類便是父類,蘋果電腦、戴爾電腦等便是子類
- 子類擁有父類的所有屬性和行為
- 子類就是一種特殊的父類
- 子類物件可以當作父類物件使用
- 子類中可以新增父類沒有的方法和屬性(好比蘋果電腦可以增加自己特有的功能)
在C++中,要繼承一個父類,我們可以使用public(公有繼承)protect(保護繼承)與private(私有繼承),三種繼承方式,使得子類對父類擁有不同的許可權,但是當今的專案開發及C++升級的語言(java、C#)只保留的public繼承,即公有繼承,所以我們在這裡只討論public繼承,具體語法如下
下邊我們就以程式碼來把電腦跟蘋果電腦例項化一下
#include <iostream> #include <string> using namespace std; class Computer { private: int m_value; public: void ComputerFun() { cout << "I'm Computer" << endl; } }; class AppleComputer : public Computer //繼承與Computer類,擁有Computer類中的所有屬性 { private: int m_appleValue; public: void AppleComputerFun() { cout << "I'm AppleComputer" << endl; } }; int main() { AppleComputer apple; apple.ComputerFun(); //呼叫的是父類的成員函式 apple.AppleComputerFun(); //呼叫的是子類新增的成員函式 system("pause"); }
編譯輸出:
在程式碼中我們將AppleComputer類繼承與Computer類,然後main函式中定義一個AppleComputer類物件,此時子類AppleComputer就擁有了父類Computer的所有屬性,包括成員變數和成員函式,所以我們就能通過子類物件直接呼叫父類的公有成員函式,其實這時候的AppleComputer類本質如下:
class AppleComputer : public Computer //繼承與Computer類,擁有Computer類中的所有屬性
{
private:
int m_value; //繼承自父類的成員變數
int m_appleValue; //子類自身的成員變數
public:
void AppleComputerFun() //子類自身的成員函式
{
cout << "I'm AppleComputer" << endl;
}
void ComputerFun() //繼承自父類的成員函式
{
cout << "I'm Computer" << endl;
}
};
這時候我們就明白了為何子類物件能直接呼叫父類中的公有成員函式。
- 子類就是一個特殊的父類
- 子類物件可以直接初始化父類物件,反之不行
- 子類物件可以直接賦值給父類物件,反之不行
從記憶體的角度考慮,子類物件初始化或賦值給父類物件,初始化或賦值的內容只是繼承自父類的那部分內容
下半邊程式碼來驗證一下:
#include <iostream>
#include <string>
using namespace std;
class Computer
{
private:
int m_value;
public:
void setPValue(int i)
{
m_value = i;
}
int getPValue()
{
return m_value;
}
};
class AppleComputer : public Computer //繼承與Computer類,擁有Computer類中的所有屬性
{
private:
int m_appleValue;
public:
void setCValue(int i)
{
m_appleValue = i;
}
int getCValue()
{
return m_appleValue;
}
};
int main()
{
AppleComputer apple;
apple.setPValue(10); //設定繼承自父類的成員變數為10
apple.setCValue(20);
Computer com = apple; //把子類直接初始化父類,這時候便是將子類中整合自父類的那部分初始給父類物件com
//也就是com中的成員變數被初始化為10
cout << "apple.getPValue() = " << apple.getPValue() << endl; //10
cout << "apple.getCValue() = " << apple.getCValue() << endl; //20
cout << "com.getPValue() = " << com.getPValue() << endl; //10
system("pause");
}
編譯輸出:
繼承是C++中程式碼複用的重要手段。通過繼承,可以獲得父類的所有功能,並且可以在子類中重寫已有的功能,或者新增新功能。
總結:
- 繼承是面向物件中類之間的一種關係
- 子類擁有父類的所有屬性和行為
- 子類物件可以作為父類物件使用
- 子類中可以新增父類沒有的方法和屬性
- 繼承是面向物件中程式碼複用的重要手段