C++筆記 第四十八課 同名覆蓋引發的問題---狄泰學院
阿新 • • 發佈:2018-12-01
如果在閱讀過程中發現有錯誤,望評論指正,希望大家一起學習,一起進步。
學習C++編譯環境:Linux
第四十八課 同名覆蓋引發的問題
1.父子間的賦值相容
子類物件可以當做父類物件使用(相容性)
子類物件可以直接賦值給父類物件
子類物件可以直接初始化父類物件
父類指標可以直接指向子類物件
父類引用可以直接引用子類物件
48-1 子類物件的相容性
#include <iostream> #include <string> using namespace std; class Parent { public: int mi; int add(int i) { mi += i; } int add(int a, int b) { mi += (a + b); } }; class Child : public Parent { public: int mv; int add(int x, int y, int z) { mv += (x + y + z); } }; int main() { Parent p; Child c; p = c; Parent p1(c); Parent& rp = c; Parent* pp = &c; rp.mi = 100; rp.add(5); //No cover of the same name occurred 沒有發生同名覆蓋? rp.add(10, 10); //No cover of the same name occurred /* Why is it compiled? 為什麼編譯不過去?*/ //pp->mv = 1000; //pp->add(1, 10, 100); return 0; }
當使用父類指標(引用)指向子類物件時
子類物件退化為父類物件
只能訪問父類中定義的成員
可以直接訪問被子類覆蓋的同名成員
2.特殊的同名函式
子類中可以重定義父類中已經存在的成員函式
這種重定義發生在繼承中,叫做函式重寫
函式重寫是同名覆蓋的一種特殊情況
3.思考
當函式重寫遇上賦值相容會發生什麼?
48-2 賦值相容的問題(**)—好好考慮
#include <iostream> #include <string> using namespace std; class Parent { public: int mi; void add(int i) { mi += i; } void add(int a, int b) { mi += (a + b); } void print() { cout << "I'm Parent." << endl; } }; class Child : public Parent { public: int mv; void add(int x, int y, int z) { mv += (x + y + z); } void print() { cout << "I'm Child." << endl; } }; void how_to_print(Parent* p) { p->print(); } int main() { Parent p; Child c; how_to_print(&p); // Expected to print: I'm Parent. how_to_print(&c); // Expected to print: I'm Child. return 0; } 執行結果 I'm Parent. I'm Parent.
4.父子間的賦值相容
問題分析
編譯期間,編譯器只能根據指標的型別判斷所指向的物件
根據賦值相容,編譯器認為父類指標指向的是父類物件
因此,編譯結果只可能是呼叫父類中定義的同名函式
在編譯這個函式的時候,編譯器不可能知道指標p究竟指向了什麼。但是編譯器沒有理由報錯。可是,編譯器認為最安全的做法是呼叫父類的print函式,因為父類和子類肯定都有相同的print函式。
5.問題—自己查詢答案
編譯器的處理方法是合理的嗎?是期望的嗎?合理,不是。
小結
子類物件可以當做父類物件使用(賦值相容)
父類指標可以正確的指向子類物件
父類引用可以正確的代表子類物件
子類中可以重寫父類中的成員函式