1,繼承在面向對象中具有舉足輕重的地位,面向對象當中的很多高級技術都和繼承是息息相關的,比如面向對象的高端課程《設計模式》中的每一種技術都和繼承有關,因此我們非常有必要在學習 C++ 時,把繼承好好的掌握;通過生活中的例子,來入手面向對象中的概念,絕對是一個很好的選擇,因為面向對象理 論起源於生活;
2,生活中的繼承是一種關系,發生在兩個實體之間,最直接的例子是兒子繼承了父親的一切東西,包括長相、性格,龍生龍指的是特征的繼承,這說明了日常生活中繼承包含的第一個層面的意思就是特征上面的獲取,老鼠兒子會打洞指的是行為的繼承,這說明了日常生活中繼承包含的第二個層面的意思就是行為上面的獲取;綜上所述,生活中的繼承指的是特征和行為的獲取;
3,面向對象中的繼承類推生活中的繼承也應該是一種關系;
4,思考:
1,類之間是否存在直接的關聯關系?
1,面向對象中的實體只有類和對象,對象是用類來創建的,所以我們有必要考慮類之間是否有關聯關系,如果類之間沒有關聯關系,則類的繼承無從談起;
5,組合關系:整體與部分的關系:
6,組合關系的描述實例分析:
1,代碼示例:
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 class Memory 7 { 8 public: 9 Memory() 10 { 11 cout << "Memory()" << endl; 12 } 13 ~Memory() 14 { 15 cout << "~Memory()" << endl; 16 } 17 }; 18 19 class Disk 20 { 21 public: 22 Disk() 23 { 24 cout << "Disk()" << endl; 25 } 26 ~Disk() 27 { 28 cout << "~Disk()" << endl; 29 } 30 }; 31 32 class CPU 33 { 34 public: 35 CPU() 36 { 37 cout << "CPU()" << endl; 38 } 39 ~CPU() 40 { 41 cout << "~CPU()" << endl; 42 } 43 }; 44 45 class MainBoard 46 { 47 public: 48 MainBoard() 49 { 50 cout << "MainBoard()" << endl; 51 } 52 ~MainBoard() 53 { 54 cout << "~MainBoard()" << endl; 55 } 56 }; 57 58 class Computer // 這個地方不僅描述了事物,也還描述了關系,里面只要有一個類不存在,電腦這個類也就不復存在了; 59 { 60 Memory mMem; 61 Disk mDisk; 62 CPU mCPU; 63 MainBoard mMainBoard; 64 public: 65 Computer() // 這里會先調用類成員的構造函數,之后調用電腦類的構造函數,這說明了組合關系;電腦類對象的創建,要依賴上述四個類的對象的創建; 66 { 67 cout << "Computer()" << endl; 68 } 69 void power() 70 { 71 cout << "power()" << endl; 72 } 73 void reset() 74 { 75 cout << "reset()" << endl; 76 } 77 ~Computer() // 電腦類析構的時候,也會將對應的類成員析構,這說明同生死;說明了電腦類對象的存在完全依賴於類成員對象的存在; 78 { 79 cout << "~Computer()" << endl; 80 } 81 }; 82 83 int main() 84 { 85 Computer c; 86 87 return 0; 88 }
1,這里各個類沒有實現具體的功能,但是這里主要是用類描述了一種生活當中 整體和部分的關系;
2,面向對象的強大主要在於它直接的描述生活里面的例子,不需要建模了,生活當中什么樣子,程序就是什么樣子,這樣很容易幫助我們開發者找到一種解決方案,面向對象程序設計理論簡化了我們當今的軟件開發,就目前而言的話,幾乎所有的大型軟件都是通過面向對象的這門理論支撐而開發的得到的,雖然說有些軟件是用 C 語言寫的,但是這門理論依然支撐着整個軟件的生命期,所以說學習 C++ 不僅僅是學習語法,還要學習面向對象的編程思想,這個例子很好的表現了這一點;
3,這個例子向我們展示了如何用代碼展示組合關系,雖然這個代碼簡單,但是后面的項目當中會經常使用這個技術;
7,組合關系的特點:
1,將其它類的對象作為當前類的成員使用;‘
1,成員變量升級了,成員變量不再是基本類型的變量,成員變量升級為其它類的對象;
2,但是這樣的話,類成員的成員變量和成員函數是一個什么樣的存儲狀態,這個還有待深刻研究;
2,成員對象的生命周期與當前類的對象相同;
1,整體與部分的關系,如果部分出了問題,整體也一定出了問題,如車的車輪、電腦的內存;
3,成員對象在用法上與普通對象完全一致;
1,組合關系是面向對象理論當中最簡單的一種關系;
8,分析繼承關系前分析組合關系的原因:
1,類之間的兩種關系為組合和繼承,先講組合是想論述類之間是真的可以存在關系的,存在了組合關系,也就可以存在繼承關系;
2,講組合關系也是因為在實際的軟件開發過程當中,發現很多開發者不會正確的使用繼承,往往該用組合關系的地方,他們用的是繼承關系,而組合關系對應的是最簡單的類之間的關系,也就對應着最簡單的代碼,我們的整個軟件本來就已經很復雜了,我們能簡單就簡單些,如果能簡單的地方弄復雜了,否則一堆的 bug 等着我們;
3,所以我們要先講組合關系,再講繼承關系,就想告訴大家,在實際的工程開發里面,我們進行設計的時候,先考慮組合關系,看下組合關系能不能滿足我們的需求、能不能描述我們實際的問題,如果可以就用組合關系,因為組合簡單,如果不可以用組合關系,則應該看看我們當前面臨的問題需要用繼承來解決,因為繼承肯定的比繼承復雜的多的多,不是一個數量級的,這就是為什么先講組合關系;
9,繼承關系:父子關系:
1,簡單的說繼承關系就是父子關系;
2,惠普電腦是一種特殊電腦,蘋果電腦也是一種特殊的電腦;惠普電腦是電腦的一個特化實例,可以說惠普電腦是一種電腦,但絕對不能說電腦是一種惠普電腦(這里賦值兼容性體現出來了,子類對象可以當做父類對象使用,父類對象不可以當做子類對象使用,子類就是一種特殊的父類),這是生活中的常識;
3,當兩個概念之間存在這種特化關系時,其實已經發生了繼承關系;惠普電腦一定會有電腦的所有特征(子類擁有父類的所有屬性和行為),但是電腦不一定有惠普電腦的特征(子類可以添加父類沒有的方法和屬性,也可以重寫父類的成員函數),因為這種關系是單向的,繼承關系必然有一個角色叫做父類,另一個角色叫做子類,子類繼承了父類的一切特征;
10,面向對象中的繼承:
1,面向對象中的繼承和生活中的繼承是相似的,也是指的父子關系;
2,這種父子關系是發生在類之間,發生在類之間的父子關系很明顯的就說明了有一個類是父類,而另一個類是子類;
11,面向對象中的繼承指類之間的父子關系:
1,子類擁有父類的所有屬性和行為;
1,惠普電腦肯定有父類的所有屬性,比如內存、硬盤、CPU、主板,行為包括開機;
2,子類就是一種特殊的父類;
1,惠普電腦是一種電腦;
1,“特殊的”寓意着除了父類的特性外還有自身的特性;
3,子類對象可以當作父類對象使用;
1,我工作需要一台電腦,這里的需要的是一個父類的對象,然而我們真正提供的惠普電腦是一個子類的對象;
2,惠普電腦可以工作,這就是說明了子類對象是可以當做父類對象使用的;
3,這是很重要的一個技術,面向對象里面的很多技術都與這個技術息息相關;
4,子類中可以添加父類沒有的方法和屬性;
1,兒子要比父親強大,長江后浪推前浪;
12,C++ 中通過下面的方式描述繼承關系:
1,代碼示例:
1 class Parent 2 { 3 int mv; 4 5 public: 6 void method(); 7 }; 8 9 class Child : public Parent // 描述繼承關系;冒號代表了繼承,繼承自 Parent 類; 10 { 11 // ... 12 };
13,繼承初體驗編程實驗:
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 class Parent 7 { 8 int mv; 9 public: 10 Parent() 11 { 12 cout << "Parent()" << endl; 13 mv = 100; 14 } 15 void method() 16 { 17 cout << "mv = " << mv << endl; 18 } 19 }; 20 21 class Child : public Parent 22 { 23 public: 24 void hello() 25 { 26 cout << "I'm Child calss!" << endl; 27 } 28 }; 29 30 int main() 31 { 32 Child c; 33 34 Parent p1 = c; // 子類對象可以當做父類對象使用; 35 Parent p2; 36 37 p2 = c; // 子類對象可以當做父類對象使用; 38 39 c.hello(); 40 c.method(); // mv = 100; 41 42 return 0; 43 }
1,子類中繼承了父類的成員函數,包括構造函數,意味着子類創建的時候,會調用父類的構造函數,以繼承父類中屬性的狀態;
2,想要使用一個已經存在的類的時候,我們不用復制粘貼它的代碼,可以繼承得到已有類的代碼,並且還可以添加新的成員;
3,繼承的深層次意義就是代碼復用;
14,繼承重要規則:
1,子類就是一個特殊的父類;
1,子類擁有父類的所有特性,所以是父類,子類可以自己添加新的特性,所以特殊;
2,子類對象可以直接初始化父類對象;
1,因為子類是一個特殊的父類;
3,子類對象可以直接賦值給父類對象;
15,繼承的意義:
1,繼承是 C++ 中代碼復用的重要手段。通過繼承,可以獲得父類的所有功能,並且可以在子類中重寫已有功能,或者添加新功能;
16,繼承的強化練習編程實驗:
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 class Memory 7 { 8 public: 9 Memory() 10 { 11 cout << "Memory()" << endl; 12 } 13 ~Memory() 14 { 15 cout << "~Memory()" << endl; 16 } 17 }; 18 19 class Disk 20 { 21 public: 22 Disk() 23 { 24 cout << "Disk()" << endl; 25 } 26 ~Disk() 27 { 28 cout << "~Disk()" << endl; 29 } 30 }; 31 32 class CPU 33 { 34 public: 35 CPU() 36 { 37 cout << "CPU()" << endl; 38 } 39 ~CPU() 40 { 41 cout << "~CPU()" << endl; 42 } 43 }; 44 45 class MainBoard 46 { 47 public: 48 MainBoard() 49 { 50 cout << "MainBoard()" << endl; 51 } 52 ~MainBoard() 53 { 54 cout << "~MainBoard()" << endl; 55 } 56 }; 57 58 class Computer 59 { 60 Memory mMem; 61 Disk mDisk; 62 CPU mCPU; 63 MainBoard mMainBoard; 64 public: 65 Computer() 66 { 67 cout << "Computer()" << endl; 68 } 69 void power() 70 { 71 cout << "power()" << endl; 72 } 73 void reset() 74 { 75 cout << "reset()" << endl; 76 } 77 ~Computer() 78 { 79 cout << "~Computer()" << endl; 80 } 81 }; 82 83 class HPBook : public Computer // 要繼承 84 { 85 string mOS; 86 public: 87 HPBook() // 先調用父類的類成員構造函數,再調用父類的構造函數,再調用自身的構造函數; 88 { 89 mOS = "Windows 8"; // 出廠預裝的 Windouw 8; 90 } 91 92 void install(string os) // 添加新功能,安裝操作系統 93 { 94 mOS = os; 95 } 96 97 void OS() // 添加新功能,查看安裝的系統 98 { 99 cout << mOS << endl; 100 } 101 }; 102 103 class MacBook : public Computer // 要繼承 104 { 105 public: 106 void OS() 107 { 108 cout << "Mac OS" << endl; 109 } 110 }; 111 112 int main() 113 { 114 HPBook hp; 115 116 hp.power(); 117 hp.install("Ubuntu 16.04 LTS"); 118 hp.OS(); 119 120 cout << endl; 121 122 MacBook mac; 123 124 mac.OS(); 125 126 return 0; 127 }
17,小結:
1,繼承是面向對象中類之間的一種關系;
2,子類擁有父類的所有屬性和行為;
3,子類對象可以當作父類對象使用;
4,子類中可以添加父類沒有的方法和屬性;
5,繼承是面向對象中代碼復用的重要手段;