您好,登錄后才能下訂單哦!
在子類繼承父類后,子類對象便可以當做父類對象使用了(兼容性)。包括:1、子類對象可以直接賦值給父類對象;2、子類對象可以直接初始化父類對象;3、父類對象可以直接指向子類對象;4、父類引用可以直接引用子類對象。那么我們來編程看看子類對象的兼容性
#include <iostream> #include <string> using namespace std; class Parent { public: int mi; void add(int v) { mi += v; } void add(int a, int b) { mi += (a + b); } }; class Child : public Parent { public: int mv; void add(int a, int b, int c) { mv += (a + b + c); } }; int main() { Parent p; Child c; p = c; Parent p1(c); Parent& rp = c; Parent* pp = &c; rp.mi = 100; rp.add(5); rp.add(10, 10); //pp->mv = 1000; //pp->add(1, 10, 100); return 0; }
我們先來看看第 38 行將子類對象 c 直接賦值給父類對象 p,這樣編譯會通過嗎?還有第 40 行的初始化操作。再將子類對象 c 賦值給父類對象的引用 rp,將父類對象的指針 pp 指向對象 c 的地址。通過 rp 調用父類對象的成員變量和成員函數,看看會報錯嗎?照理說這塊應該會發生同名覆蓋,我們看看編譯結果
編譯是通過的,也就證明沒有發生同名覆蓋。那么我們再來將第 49 和 50 行的注釋去掉,看看通過指針 pp 指向的子類對象 c 直接調用子類對象的成員變量和成員函數會通過嗎?
我們看到編譯出錯了。下來我們來說下當使用父類指針(引用)指向子類對象時,子類對象便退化為父類對象,只能訪問父類中定義的成員,可以直接訪問被子類覆蓋的同名成員。這也就不難解釋上面沒有發生同名覆蓋以及通過指針來調用子類對象的成員變量和成員函數出錯的情況了。
在子類中可以重定義父類中已經存在的成員函數,這種重定義發生在繼承中,叫做函數重寫。函數重寫是同名覆蓋的一種特殊情況。當函數重寫遇上賦值兼容會發生什么呢?我們通過是來代碼來分析下
#include <iostream> #include <string> using namespace std; class Parent { public: void print() { cout << "I'm Parent!" << endl; } }; class Child : public Parent { public: void print() { cout << "I'm Child!" << endl; } }; void how_to_print(Parent* p) { p->print(); } int main() { Parent p; Child c; p.print(); // I'm Parent! c.print(); // I'm Child! cout << endl; how_to_print(&p); // I'm Parent! how_to_print(&c); // I'm Child! return 0; }
我們分別在父類和子類中定義 print 函數,打印相關信息。我們期望的是 p.print() 打印的是 I'm Parent!;c.print() 打印的是 I'm Child!;在調用全局函數 how_to_print() 時,如果傳入的是父類指針,我們期望打印的是 I'm Parent!,如果傳入的是子類指針,則打印的是 I'm Child!。下來我們來編譯看看結果
我們直接調用的時候打印的是對的,但是在傳入對象的時候,打印的是錯的。我們傳入的是子類對象,但是打印出來的是父類的函數,我們會不會很奇怪呢?在編譯期間,編譯器只能根據指針的類型判斷所指向的對象,根據賦值兼容,編譯器認為父類指針指向的是父類對象。因此,編譯結果只可能是調用父類中定義的同名函數。那么在編譯到 how_to_print(Parent* p) 這個函數時,編譯器不可能知道指針 p 究竟指向了什么。但是編譯器沒有理由報錯。于是乎,編譯器認為最安全的做法是調用父類的 print 函數,因為父類和子類肯定都有相同的 print 函數。因此便出現了這個編譯結果,那么編譯器的處理方法是合理的嗎?是期望的嗎?顯然從安全的角度來說,它的處理是合理的,但卻不是我們所期望的。在后面我們會繼續講解這個問題的。
通過對同名覆蓋的學習,總結如下:1、子類對象可以當做父類對象使用(賦值兼容);2、父類指針可以正確的指針子類對象;3、父類引用可以正確的代表子類對象;4、子類中可以重寫父類中的成員函數。
歡迎大家一起來學習 C++ 語言,可以加我QQ:243343083。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。