多態

多態

面向對象三大概念:封裝、繼承、多態;
多態:從某個函數中取得“正確的”行爲,而又不依賴於實際使用的到底是哪一種函數,這就是所謂的多態性。
一個帶有虛函數的類型被稱爲一個多態類型;要在C++裏取得多態性的行爲,被調用的函數必須是虛函數,而對象則必須是通過指針或者引用去操作的

爲什麼需要多態?

若子類定義和父類中原型相同的函數會發生什麼?

#include <iostream>

using namespace std;

class Parent
{
public:
	void print(){ 
		cout<<"Parent:print() do..."<<endl; 
	}
}; 

class Child : public Parent
{
public:
	void print(){
		cout<<"Child:print() do..."<<endl; 
	}
};


int main(){
	//子類和父類中函數同名,父類中同名含默認被 隱藏 
	Child child;
	child.print();
	//
	Parent *p = NULL;
	p = &child;
	(*p).print();
	//怎麼通過分辨符訪問父類中被隱藏的函數? 
	child.Parent::print();
	system("pause");
	return 0;
Child:print() do...
Parent:print() do...
Parent:print() do...
請按任意鍵繼續. . .

父類中被重寫的函數依然會繼承給子類,默認情況下子類中重寫的函數將隱藏父類中的函數,通過作用域分辨符::可訪問到父類中被隱藏的函數
C/C++是靜態編譯型語言,在編譯時,編譯器自動根據指針的類型判斷指向的是一個什麼的對象。
1、在編譯此函數的時,編譯器不可能知道指針 p 究竟指向了什麼。
2、編譯器沒有理由報錯。
3、編譯器認爲最安全的做法是編譯到父類的print函數,因爲父類和子類肯定都有相同的print函數。

面向對象新需求

編譯器的默認選擇不是我們所想要的;根據實際的對象類型來判斷重寫函數的調用;
若父類指針指向父類對象則代用父類中的函數;
若父類指針指向子類對象則調用子類中的函數;
在這裏插入圖片描述
解決方法:
使用virtual關鍵字對多態進行支持;
使用virtual聲明的函數被重寫後可展現多態特性;

多態條件

要有繼承關係、存在函數重寫(C虛函數)、存在父類指針(父類引用)指向子類對象;
多態理論基礎
靜態聯編和動態聯編
聯編指一個程序模塊、代碼之間互相關聯的過程;
靜態聯編(static binding)是程序匹配、連續在編譯階段實現,即早期匹配,如重載函數使用靜態聯編;
動態聯編指程序聯編推遲到運行時進行,即晚期聯編(遲綁定),如switch語句和if語句是動態聯編;
C++與C相同,是靜態編譯型語言;
編譯時,編譯器自動根據指針的類型判斷指向是一個什麼樣的對象,所以編譯器認爲父類指針指向的父類對象;
程序未運行時無法判斷父類指針指向的具體對象(父類或子類);
從程序安全角度,編譯器假定父類指針指向父類對象,所以編譯的結果爲調用父類的成員函數,該特性即爲靜態聯編

Question
怎麼理解多態
多態是同樣的調用語句有多種不同的表現形態;
實現的三個條件:有繼承、有virtual重寫、有父類指針(引用)指向子類對象;
C++實現:
virtual關鍵字告訴編譯器該函數要支持多態;不是根據指針類型判斷調用關係,而是根據指針指向的實際對象類型來判斷調用關係;
根據實際的對象類型來判斷重寫函數的調用;
多態是設計模式的基礎?
函數指針做函數參數是多態實現的基礎?
多態原理?
對重寫、重載理解
函數重載:
必須在同一個類中進行;
子類無法重載父類的函數,父類同名函數將被名稱覆蓋
重載是在編譯期間根據參數類型和個數決定函數調用
函數重寫
必須發生在父類與子類之間
父類與子類中的函數必須有完全相同的原型
使用virtual聲明後,能夠產生多態(若不使用virtual,那是重定義);
多態在運行期間根據具體對象的類型決定函數調用
C++編譯器多態實現原理理解
是否可將每個成員函數夠聲明爲虛函數,爲什麼?

發佈了130 篇原創文章 · 獲贊 71 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章