类与面向对象的精华:继承【C++继承】
- 引入繼承
- 為什么需要繼承?
- 簡單舉例
- 繼承
- 定義
- 定性 is-a 而不是 has-a
- is-a
- has-a
- 語法
- 繼承方式
- 繼承方式影響了什么?
- 公有繼承 public
- 私有繼承 private
- 保護繼承 protected
- 繼承方式結論
- 派生類的組成
- 組成圖示
- 說明
- sizeof(父類 / 子類)
- 繼承的內存模型
引入繼承
為什么需要繼承?
C++中代碼的可重用性通過繼承機制來實現。
簡單舉例
代碼演示:
#include <iostream>using namespace std;class Student { public:void study(string course){cout << " i am a student , i am learning " << course << endl;}void eat(string food){cout << " i am eating " << food << endl;} };class Teachers { public:void tech(string course){cout << " i am teacher , i am teaching " << course << endl;}void eat(string food){cout << " i am eating " << food << endl;} };int main() {return 0; }上面代碼中,Teachers類 和 Student 類 具有相同的方法 eat ,那么就可以將 eat 方法進行抽象。
提取 Teachers類 和 Student 類 的公共方法到 Human類,讓Teachers類 和 Student 類 繼承 Human類 實現代碼可重用。
代碼演示:
運行結果:
結論:
繼承是一種設計的結果,通常是發生于一套類庫中的,設計代碼重用的方式。
這種關系是一種設計而為之,不是想繼承,就可隨便繼承的。
繼承
定義
類的繼承,是新的類從已有類那里得到已有的特性。
從已有類產生新類的過程就是類的派生。
定性 is-a 而不是 has-a
is-a
is-a 是一種屬于關系。
例如:
狗屬于一種動物。
可以設計一個 Animal 類,Dog 類作為Animal 類(基類)的派生類;
車屬于一種交通工具,在面向對象中表現為一種繼承關系。
設計一個 Vehicle 類,Car 類作為 Vehicle 類(基類)的派生類。
has-a
has-a 是一種包含、組合關系。
例如:
車包含方向盤、輪胎、發動機。
但不能說方向盤/輪胎/發動機是一種車。
正確的應該說車聚合(包含)了方向盤、輪胎、發動機。
狗包含腿、尾巴。
但不能說腿、尾巴是一種狗。
如果 A is a B,則 B 是 A 的基類,A 是 B 的派生類。為繼承關系。
如果 A 包含 B,則 B 是 A 的組成部分,為聚合關系,可以由組成部分聚合成為一個類。
語法
class 派生類名:[繼承方式] 基類名 {派生類成員聲明; };默認的繼承方式是 private 私有繼承。
一個派生類可以同時有多個基類,這種情況稱為多重繼承。
派生類只有一個基類,稱為單繼承。
繼承方式
繼承方式影響了什么?
繼承方式規定了子類如何訪問從基類繼承的成員。
繼承方式有 public, private, protected。
繼承方式不影響派生類的訪問權限,影響了從基類繼承而來的成員的訪問權限,包括派生類內的訪問權限和派生類對象的訪問權限。
代碼演示:
編譯器報錯:
公有繼承 public
基類的公有成員和保護成員在派生類中保持原有訪問屬性,其私有成員仍為基類的私有成員。
私有繼承 private
基類的公有成員和保護成員在派生類中成了私有成員,其私有成員仍為基類的私有成員。
保護繼承 protected
基類的公有成員和保護成員在派生類中成了保護成員,其私有成員仍為基類的私有成員。
繼承方式結論
派生類的組成
組成圖示
派生類中的成員,包含兩大部分,一類是從基類繼承過來的,一類是自己增加的成員。
從基類繼承過過來的表現其共性,而新增的成員體現了其個性。
說明
全盤接收,除了構造器與析構器。
基類有可能會造成派生類的成員冗余,所以說基類是需設計的。
派生類有了自己的個性,使派生類有了意義。
sizeof(父類 / 子類)
代碼演示:
#include <iostream>using namespace std;class Base { public:int pub;//pretected 對于外界訪問屬性來說,等同于私有,但可以派生類中可見。 protected:int pro; private:int pri; };class Drive :public Base { public:void func()//子類中的訪問屬性{pub = 10;pro = 100;//pri = 1000;} public:int a; protected:int b; private:int c; };int main() {cout << "sizeof(Base) = " << sizeof(Base) << endl;cout << "sizeof(Drive) = " << sizeof(Drive) << endl;return 0; }運行結果:
繼承的內存模型
#include <iostream> #include <typeinfo>using namespace std;class A { public:A(){cout << this << endl;cout << typeid(this).name() << endl;}int a; };class B :public A { public:B(){cout << this << endl;cout << typeid(this).name() << endl;}int b; };class C :public B { public:C(){cout << this << endl;cout << typeid(this).name() << endl;}void func(){cout << &a << endl;cout << &b << endl;cout << &c << endl;}int c; };int main() {C c;cout << "&c " << &c << endl;cout << "*************" << endl;c.func();return 0; }運行結果:
類A,B,C 和對象 c 地址相同。
類A,B,C 的類型不同,分別為 class A*, class B*, class C*。
從結果得出:子類生成對象,先構造父類,后構造子類。
總結
以上是生活随笔為你收集整理的类与面向对象的精华:继承【C++继承】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 取代C语言标准输入输出:cin 和 co
- 下一篇: 派生类的构造【C++继承】