1,父子間的衝突是由繼承帶來的,兩個類之間存在了繼承的關係,必然的會帶來一 些問題,本文要討論的是父子之間成員變數或成員函數的命名問題; 2,思考: 1,子類中是否可以定義父類中的同名成員? 1,可以,本文先編程解決這個問題; 2,這個問題就是同名覆蓋問題; 2,如果可以,如何區分?如果不可以,為什 ...
1,父子間的衝突是由繼承帶來的,兩個類之間存在了繼承的關係,必然的會帶來一 些問題,本文要討論的是父子之間成員變數或成員函數的命名問題;
2,思考:
1,子類中是否可以定義父類中的同名成員?
1,可以,本文先編程解決這個問題;
2,這個問題就是同名覆蓋問題;
2,如果可以,如何區分?如果不可以,為什麼?
3,同名成員變數編程實驗:
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 class Parent 7 { 8 public: 9 int mi; 10 }; 11 12 class Child : public Parent 13 { 14 public: 15 int mi; // 編譯結果通過,子類可以定義父類裡面的同名變數; 16 }; 17 18 int main() 19 { 20 Child c; 21 22 c.mi = 100; // mi 究竟是子類自定義的,還是從父類繼承得到的? 23 24 return 0; 25 }
4,父子間的衝突(同名覆蓋):
1,子類可以定義父類中的同名成員;
2,子類中的成員將隱藏父類中的同名成員;
1,編譯器認為已經從父類中繼承得到這個成員了,又自定義了一個同名成員,目的只有一個,就是你想要自己自定義的同名成員、而不想要從父類那裡繼承得到的同名成員,因此會產生同名覆蓋現象;
3,父類中的同名成員依然存在於子類中;
1,隱藏、不是銷毀;
4,通過作用域分辨符(::)訪問父類中的同名成員;
5,訪問父類中的同名成員方式:
1,Child c;
2,c.mi = 100; // 子類中的 mi;
3,c.Parent::mi = 1000; // 父類中的 mi;
6,同名成員變數深度分析編程實驗:
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 namespace A 7 { 8 int g_i = 0; 9 } 10 11 namespace B 12 { 13 int g_i = 1; // 同名的全局變數,但是位於兩個不同的命名空間; 14 } 15 16 class Parent 17 { 18 public: 19 int mi; 20 21 Parent() 22 { 23 cout << "Parent() : " << "&mi = " << &mi << endl; 24 } 25 }; 26 27 class Child : public Parent 28 { 29 public: 30 int mi; // 編譯器沒有簡單的對同名成員報錯,是因為作用域,雖然兩個成員的名字相同,但是出於不同的作用域當中;同命名空間的本質是一樣的; 31 32 Child() 33 { 34 cout << "Child() : " << "&mi = " << &mi << endl; 35 } 36 }; 37 38 int main() 39 { 40 Child c; // Parent() : &mi = 0xbfb43a08 Child() : &mi = 0xbfb43a0c 41 42 c.mi = 100; 43 44 c.Parent::mi = 1000; 45 46 cout << "&c.mi = " << &c.mi << endl; // &c.mi = 0xbfb43a0c,證明直接訪問的是子類的 mi; 47 cout << "c.mi = " << c.mi << endl; // c.mi = 100; 48 49 cout << "&c.Parent::mi = " << &c.Parent::mi << endl; // &c.Parent::mi = 0xbfb43a08; 作用域分辨符訪問父類 mi; 50 cout << "c.Parent::mi = " << c.Parent::mi << endl; // c.Parent::mi = 1000; 51 52 return 0; 53 }
1,父類和子類可以產生同名覆蓋衝突,但是通過作用域分辨符可以解決這個問 題;
7,再論重載:
1,類中的成員函數可以進行重載:
1,重載函數的本質為多個不同的函數;
2,函數名和參數列表是唯一的標識;
3,函數重載必鬚髮生在同一個作用域中;
8,問題:
1,子類中定義的函數是否能重載父類中的同名函數?
1,將父子間的衝突問題上升到成員函數了;
9,父子間的函數重載編程實驗:
1,繼承父類成員函數,累加父類的同名成員;
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 class Parent 7 { 8 public: 9 int mi; 10 11 void add(int v) 12 { 13 mi += v; 14 } 15 16 void add(int a, int b) 17 { 18 mi += (a + b); 19 } 20 }; 21 22 class Child : public Parent 23 { 24 public: 25 int mi; 26 }; 27 28 int main() 29 { 30 Child c; 31 32 c.mi = 100; 33 34 c.Parent::mi = 1000; 35 36 cout << "c.mi = " << c.mi << endl; // c.mi = 100; 37 38 cout << "c.Parent::mi = " << c.Parent::mi << endl; // c.Parent::mi = 1000; 39 40 c.add(1); // 繼承自父類的成員函數;這個函數得到的 mi 不知道後面還要定義一個子類,它知道的 mi 只是父類中的,這個時候 mi 的作用域在父類中,所以給了父類中的 mi 做累加; 41 c.add(2, 3); // 繼承自父類的成員函數; 42 43 cout << "c.mi = " << c.mi << endl; // c.mi = 100; 44 45 cout << "c.Parent::mi = " << c.Parent::mi << endl; // c.Parent::mi = 1006;累加到父類中的 mi 了; 46 47 return 0; 48 }
2,函數的同名覆蓋:
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 class Parent 7 { 8 public: 9 int mi; 10 11 void add(int v) 12 { 13 mi += v; 14 } 15 16 void add(int a, int b) 17 { 18 mi += (a + b); 19 } 20 }; 21 22 class Child : public Parent 23 { 24 public: 25 int mi; 26 27 void add(int x, int y, int z) 28 { 29 mi += (x + y + z); 30 } 31 }; 32 33 int main() 34 { 35 Child c; 36 37 c.mi = 100; 38 39 c.Parent::mi = 1000; 40 41 cout << "c.mi = " << c.mi << endl; // c.mi = 100; 42 43 cout << "c.Parent::mi = " << c.Parent::mi << endl; // c.Parent::mi = 1000; 44 45 // c.add(1); // 編譯器顯示沒有匹配的函數調用 Child::add(int);同名成員函數覆蓋,並沒有重載,作用域不同; 46 // c.add(2, 3); // 編譯器顯示沒有匹配的函數調用 Child::add(int, int);同名成員函數覆蓋,並沒有重載,作用域不同; 47 48 c.Parent::add(1); // 作用域分辨符解決同名成員函數覆蓋問題; 49 c.Parent::add(2, 3); // 作用域分辨符解決同名成員函數覆蓋問題;累加父類中的 mi 50 51 c.add(4, 5, 6); // 調用子類中的 add(),預設情況下訪問的就是子類中的 mi,這個地方發生了同名覆蓋; 52 53 cout << "c.mi = " << c.mi << endl; // c.mi = 115;預設訪問的 mi 是子類中的 mi; 54 55 cout << "c.Parent::mi = " << c.Parent::mi << endl; // c.Parent::mi = 1006;前兩次累加的是父類中的 mi; 56 57 return 0; 58 }
10,父子間的衝突:
1,子類中的函數將隱藏父類的同名函數;
2,子類無法重載父類中的成員函數;
1,因為它們處於不同的作用域;
3,使用作用域分辨符訪問父類中的同名函數;
1,類名加上作用域分辨符;
4,子類可以定義父類中完全相同的成員函數;
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 class Parent 7 { 8 public: 9 int mi; 10 11 void add(int v) 12 { 13 mi += v; 14 } 15 16 void add(int a, int b) 17 { 18 mi += (a + b); 19 } 20 }; 21 22 class Child : public Parent 23 { 24 public: 25 int mi; 26 27 void add(int v) // 同名覆蓋;函數重寫; 28 { 29 mi += v; 30 } 31 32 void add(int a, int b) // 同名覆蓋;函數重寫; 33 { 34 mi += (a + b); 35 } 36 37 void add(int x, int y, int z) // 重載; 38 { 39 mi += (x + y + z); 40 } 41 }; 42 43 int main() 44 { 45 Child c; 46 47 c.mi = 100; 48 49 c.Parent::mi = 1000; 50 51 cout << "c.mi = " << c.mi << endl; // c.mi = 100; 52 53 cout << "c.Parent::mi = " << c.Parent::mi << endl; // c.Parent::mi = 1000; 54 55 c.add(1); // 同名覆蓋; 56 c.add(2, 3); // 同名覆蓋; 57 c.add(4, 5, 6); // 函數重載; 58 59 cout << "c.mi = " << c.mi << endl; // c.mi = 121;函數同名覆蓋和重載,都是預設訪問的子類的 mi; 60 61 cout << "c.Parent::mi = " << c.Parent::mi << endl; // 父類中的函數被同名覆蓋,未有訪問父類中的 mi; 62 63 return 0; 64 }
11,小結:
1,子類可以定義父類中的同名成員;
2,子類中的成員將隱藏父類中的同名成員;
1,包括同名成員變數和同名成員函數;
2,重寫的依據;
3,這就是同名覆蓋;
3,子類和父類中的函數不能構成重載關係;
1,作用域不同;
4,子類可以定義父類中完全相同的成員函數;
1,作用域不同;
5,使用作用域分辨符訪問父類中的同名成員;
1,父類名加上作用域分辨符;