如果父類成員和子類成員名字相同是否允許?會發生什么?
同名覆蓋
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
#include<iostream> using namespace std; class Base { public : int m_data; Base():m_data(1) //父類初始化為1 { } }; class Derived : public Base { public : int m_data; Derived():m_data(2) //子類初始化為2 { } }; int main() { Derived d; //父類的m_data被隱藏了,但仍存在,可以通過::符訪問 cout<< "base data: " <<d.Base::m_data<<endl; //直接訪問m_data得到的是子類成員的值 cout<< "derived data: " <<d.m_data<<endl; //驗證兩個int剛好是8字節,說明d對象有兩個整型數 cout<< sizeof (d)<<endl; return 0; } |
運行結果
base data: 1
derived data: 2
8
說明父類和子類是允許存在同名成員的,只不過父類的成員被編譯器隱藏了,正常訪問得到的是子類成員的值。
那么如果是函數同名呢?
函數重寫
函數重寫是同名覆蓋的一種特殊情況,即子類中重新實現父類中的同名函數,屬于同名覆蓋
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
#include<iostream> using namespace std; class Base { public : void print() { cout<< "Base class" <<endl; } }; class Derived : public Base { public : void print() { cout<< "Derived class" <<endl; } }; int main() { Derived d; d.Base::print(); //父類函數被隱藏 d.print(); return 0; } |
運行結果
Base class
Derived class
如果調用how_to_print
函數,期望傳入父類對象時調用父類打印函數,傳入子類對象時調用子類對象函數
1
2
3
4
5
6
7
8
9
10
11
12
|
void how_to_print(Base* p) { p->print(); //期望根據對象選擇相應函數,不能實現 } int main() { Base b; Derived d; how_to_print(&b); how_to_print(&d); return 0; } |
結果卻是都打印Base class
Base class
Base class
結果沒有符合預期,分析:
1.傳入父類對象b的地址時,父類指針指向父類對象,打印正常;
2.傳入子類對象d的地址時,父類指針指向子類對象,此時由于賦值兼容性(子類對象可以當作父類對象使用),子類對象退化為父類對象(父類指針只能訪問父類成員),編譯器認為父類指針指向的是父類對象,因此最終調用了父類的打印函數
以上結果是合理的,卻沒有符合預期的目的,這也是函數重寫帶來的問題。如果不能實現以上目的,函數重寫是沒有意義的,那么如何實現父類指針(引用)指向:
- 父類對象,調用父類函數
- 子類對象,調用重寫函數
實際上以上行為就是多態
多態
所謂多態,即同樣的調用語句,在實際運行時存在不同的表現狀態,依據則是對象的類型不同
要實現上文中函數重寫的多態,需要引入virtual關鍵字,C++原生支持多態
- 通過使用virtual關鍵字對多態進行支持
- 被virtual聲明的函數被重寫后具有多態特性
- 被virtual聲明的函數叫做虛函數
在父類函數print聲明前添加virtual關鍵字,print函數成為虛函數,子類重寫的函數也將自動變成虛函數,這樣就可以實現多態
1
2
3
4
5
6
7
8
|
class Base { public : virtual void print() //加virtual變成了虛函數 { cout<< "Base class" <<endl; } }; |
運行結果
Base class
Derived class
多態的意義:
在程序運行過程中展現出動態的特性函數重寫必須多態實現,否則沒有意義多態是面向對象組件化程序設計的基礎特性
總結
同名覆蓋是繼承時發生在父類和子類之間,子類同名成員覆蓋(屏蔽)父類同名成員的現象;函數重寫也是同名覆蓋,函數重寫多態實現才有意義,C++通過virtual支持多態多態是面向對象組件化程序設計的基礎特性
原文鏈接:https://blog.csdn.net/to_free/article/details/120538227