1,被忽略的細節: 1,冒號( :)表示繼承關係,Parent 表示被繼承的類,public 的意義是什麼? 2,有趣的問題: 1,是否可以將繼承語句中的 public 換成 protected 或者 private?如果可以,與 public 繼承有什麼區別? 3,有趣的嘗試編程實驗: 1,pro ...
1,被忽略的細節:
1,冒號( :)表示繼承關係,Parent 表示被繼承的類,public 的意義是什麼?
1 class Parent 2 { 3 4 }; 5 6 class Child : public Parent 7 { 8 9 };
2,有趣的問題:
1,是否可以將繼承語句中的 public 換成 protected 或者 private?如果可以,與 public 繼承有什麼區別?
3,有趣的嘗試編程實驗:
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 class Parent 7 { 8 }; 9 10 class Child_A : public Parent 11 { 12 }; 13 14 class Child_B : protected Parent 15 { 16 }; 17 18 class Child_C : private Parent 19 { 20 }; 21 22 int main() 23 { 24 return 0; 25 }
1,protected 和 private 地位對等,推理的角度可以過,實際的編譯結果也是同樣的結論;
2,本文主要分析這三種繼承方式有何不同;
4,不同的繼承方式(這是父類成員在子類中被外界訪問的級別):
1,C++ 中支持三種不同的繼承方式;
1,public 繼承:
1,父類成員在子類中保持原有訪問級別;
2,private 繼承:
1,父類成員在子類中變為私有成員;
3,protected 繼承:
1,父類中的公有成員變為保護成員,其它成員保持不變;
2,繼承成員的屬性:
1,Max{繼承方式,父類成員訪問屬性};
2,C++ 中的預設繼承方式為 private;
3,繼承與訪問級別深度實踐編程實驗:
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 class Parent 7 { 8 protected: 9 int m_a; 10 protected: 11 int m_b; 12 public: 13 int m_c; 14 15 void set(int a, int b, int c) 16 { 17 m_a = a; 18 m_b = b; 19 m_c = c; 20 } 21 }; 22 23 class Child_A : public Parent 24 { 25 public: 26 void print() 27 { 28 cout << "m_a" << m_a << endl; 29 cout << "m_b" << m_b << endl; 30 cout << "m_c" << m_c << endl; 31 } 32 }; 33 34 class Child_B : protected Parent 35 { 36 public: 37 void print() 38 { 39 cout << "m_a" << m_a << endl; 40 cout << "m_b" << m_b << endl; 41 cout << "m_c" << m_c << endl; 42 } 43 }; 44 45 class Child_C : private Parent 46 { 47 public: 48 void print() 49 { 50 cout << "m_a" << m_a << endl; 51 cout << "m_b" << m_b << endl; 52 cout << "m_c" << m_c << endl; 53 } 54 }; 55 56 int main() 57 { 58 Child_A a; 59 Child_B b; 60 Child_C c; 61 62 a.m_c = 100; 63 // b.m_c = 100; // Child_B 保護繼承自 Parent, 所以所有 public 成員全部變成了 protected 成員, 因此外界無法訪問; 64 // c.m_c = 100; // Child_C 私有繼承自 Parent, 所以所有的成員全部變成了 private 成員, 因此外界無法訪問; 65 66 a.set(1, 1, 1); 67 // b.set(2, 2, 2); // 保護繼承; 68 // c.set(3, 3, 3); // 私有繼承; 69 70 a.print(); // 繼承方式隻影響繼承自父類成員的訪問方式,外界訪問子類方式無影響; 71 b.print(); // 繼承方式隻影響繼承自父類成員的訪問方式,外界訪問子類方式無影響; 72 c.print(); // 繼承方式隻影響繼承自父類成員的訪問方式,外界訪問子類方式無影響; 73 74 return 0; 75 }
1,父類中的訪問級別影響著子類的訪問,但是繼承級別不影響子類的訪問、影響其它外部類訪問父類中的成員;
5,遺憾的事實:
1,一般而言,大型的 C++ 工程項目中只使用 public 繼承;
1,這已經足夠了;
2,保護繼承和私有繼承根本就沒什麼用;
2,C++ 的派生語言只支持一種繼承方式(public 繼承);
1,Java、C# 等語言只有一種繼承方式即 public 繼承方式;
3,protected 和 private 繼承帶來的複雜性遠大於實用性;
1,僅在學術研究領域研究;
6,C++ 派生語言初探編程實驗:
1,D 語言(在 Linux 中用 gdc 編譯,生成 *.out 文件):
1 module D_Demo; // 將下麵的所有代碼定義為模塊,模塊名字為 2 D_Demo; 3 4 import std.stdio; // import 同 include 5 import std.string; // import 同 include 6 7 class Obj // 這裡定義了一個 Obj 類 8 { 9 protected: 10 string mName; 11 string mInfo; 12 13 public: 14 this() // 這是 D 語言中的構造函數,D 語言中的構造函數統一的用 this 這個關鍵字表示,由 C++ 進化而來; 15 { 16 mName = "Object"; 17 mInfo = ""; 18 } 19 20 string name() // 定義兩個成員函數; 21 { 22 return mName; 23 } 24 25 string info() 26 { 27 return mInfo; 28 } 29 } 30 31 class Point : Obj // 定義了一個類 Point,其繼承自 Obj,D 語言中的繼承方式預設的是 public 繼承; 32 { 33 private: 34 int mX; 35 int mY; 36 37 public: 38 this(int x, int y) 39 { 40 mX = x; 41 mY = y; 42 mName = "Point"; 43 mInfo = format("P(%d, %d)", mX, mY); // 和 C 語言中的語法規則一樣; 44 } 45 46 int x() 47 { 48 return mX; 49 } 50 51 int y() 52 { 53 return mY; 54 } 55 } 56 57 void main(string[] args) // 程式運行的入口; 58 { 59 writefln("D Demo"); // D Demo;列印語句之後空一行,同 printf; 60 61 Point p = new Point(1, 2); // 動態生成 Point 對象; 62 63 writefln(p.name()); // Point,公有繼承; 64 writefln(p.info()); // P(1, 2),公有繼承; 65 }
1,沒學過 D 語言,但是要讀懂 D 語言的代碼是比較容易的;
2,如果因工作需要要學習 D 語言程式設計,將是輕而易舉的事情;
2,C# 語言(Linux 中用 gmcs 編譯,生成 *.exe 文件):
1 class Obj // 定義一個類 Obj; 2 { 3 protected string mName; // 訪問屬性 protected; 4 protected string mInfo; 5 6 public Obj() // 無返回值,函數名同類名,即構造函數,訪問屬性為 public; 7 { 8 mName = "Object"; 9 mInfo = ""; 10 } 11 12 public string name() 13 { 14 return mName; 15 } 16 17 public string info() 18 { 19 return mInfo; 20 } 21 } 22 23 class Point : Obj // 定義一個類 Point,繼承自 Obj,只有一種 public 繼承方式; 24 { 25 26 private int mX; 27 private int mY; 28 29 public Point(int x, int y) // 構造函數; 30 { 31 mX = x; 32 mY = y; 33 mName = "Point"; 34 mInfo = "P(" + mX + ", " + mY + ")"; // 通過 + 操作符來連接字元串和整型變數,最終得到一個字元串;C++ 中可以通過重載全局的 + 操作符就能夠連接一個字元串和一個整型變數最終得到一個字元串,別的語言中的特性,不明白的話,考慮下在 C++ 中如何實現; 35 } 36 37 public int x() 38 { 39 return mX; 40 } 41 42 public int y() 43 { 44 return mY; 45 } 46 } 47 48 class Program 49 { 50 public static void Main(string[] args) // 程式入口 51 { 52 System.Console.WriteLine("C# Demo"); // C# Demo 53 54 Point p = new Point(1, 2); 55 56 System.Console.WriteLine(p.name()); // Point 57 System.Console.WriteLine(p.info()); // P(1, 2) 58 59 } 60 }
3,Java 程式:
1 class Obj 2 { 3 protected String mName; 4 protected String mInfo; 5 6 public Obj() 7 { 8 mName = "Object"; 9 mInfo = ""; 10 } 11 12 public String name() 13 { 14 return mName; 15 } 16 17 public String info() 18 { 19 return mInfo; 20 } 21 } 22 23 class Point extends Obj // extends 表示公有繼承,更加直觀; 24 { 25 26 private int mX; 27 private int mY; 28 29 public Point(int x, int y) 30 { 31 mX = x; 32 mY = y; 33 mName = "Point"; 34 mInfo = "P(" + mX + ", " + mY + ")"; 35 } 36 37 public int x() 38 { 39 return mX; 40 } 41 42 public int y() 43 { 44 return mY; 45 } 46 } 47 48 class Program { 49 public static void main(String[] args){ // 程式運行如口 50 System.out.println("Java Demo"); // Java Demo 51 52 Point p = new Point(1, 2); 53 54 System.out.println(p.name()); // Point 55 System.out.println(p.info()); // P(1, 2) 56 } 57 }
1,現在已經有能力讀懂 D、C#、Java 語言程式了;
1,C#、Java 可以從事網路開發、游戲開發;
2,D 語言可以從事系統開發;
2,工程裡面,僅僅使用 public 繼承就夠了;
7,小結:
1,C++ 中支持 3 種不同的繼承方式;
2,繼承方式直接影響父類成員在子類中的訪問屬性;
3,一般而言,工程中只使用 public 的繼承方式;
4,C++ 的派生語言中只支持 public 繼承方式;