1. 程式人生 > >C++虛擬函式多型原理-最直白的講解

C++虛擬函式多型原理-最直白的講解

C++的主要特點是抽象,繼承,封裝和多型。我們先理解抽象是什麼?在這之前,首先我問你C++是什麼,是用來幹什麼的?

一切的語言都是用來描述現實世界的 ,C++也是.C++的任何特性都是為了去描述這個世界,併為其解決提供方法。但是C++還是並不能完全去描述這個世界,因為現實世界是無法完全認知的,只能不斷去認知的,扯遠了,感到到了哲學這段。抽象?例如現實世界的人類,書,樹,桌子,椅子等名詞都是一種對某些具有共同特徵實體的抽象描述。感覺有點可以用集合來理解。難道每次去描述人時都是直立行走,兩隻眼睛,一直嘴巴?所以需要抽象來解決這個問題。因此抽象就對應了C++中的類。再比如描述人時,你還是不知道它是亞洲人,歐洲人,還是非洲人,或許是外星人?所以又出現了繼承這一概念,對應人集合中的子集。封裝就是對類中的資訊進行分級,主要是針對類的例項來說,有些東西你可以呼叫,有些東西你不能呼叫。也就是類的設計者並不想讓類的例項為所欲為。突然想到人到底有沒有靈魂一說呢?假如上帝是人類的設計者,每個人就是一個例項,將靈魂屬性進行隱藏,你又如何知道它的存在呢?或許只有對例項程式碼進行研究透,搞明白任何原理才知道吧。

定義下多型的含義:

通過父類型別的指標或者引用指向子類物件。通過該指標或者引用就可以實現只能呼叫子類的虛擬函式以及繼承父類的函式,而無法對子類其它的函式進行呼叫的功能。

先來討論一下子類和父類的關係?先討論函式。

子類會繼承父類的成員變數和成員函式,同時子類也可以有自己的成員函式和成員變數。如果子類的成員變數的名稱和父類的成員變數名稱一樣,呼叫子類例項時,是呼叫父類變數還是子類變數呢?如果不加作用域的情況下,呼叫子類變數。這是隱藏。子類將父類的變數隱藏了。同樣:如果子類的成員函式的名稱和父類的成員函式名稱一樣時,儘管返回值或者引數型別,引數個數也不一樣,呼叫子類例項時,父類的同名成員函式均會被隱藏,無法呼叫。至於如果子類有多個成員函式的名稱一樣,其他不同,則他們彼此之間的關係為過載。根據引數型別,返回值型別而呼叫不同的成員函式。

假如現在有一個函式:輸入為人型別比如亞洲或者歐洲或者非洲啊,輸出為該人型別的膚色,那如何傳引數呢?形參如何寫呢?第一種是對該函式進行過載,這樣會很浪費程式碼。

第二種就是用多型了,利用子類和父類之間的多型性來解決,來對應形參和實參之間的關係。形參為父類例項引用,實參為子類例項,這樣呼叫的虛擬函式就對應了相應實參型別的虛擬函式。

程式碼如下:

class CBse
{
public:
    virtual void f1(){}
};
class CDerive1 : public CBse
{
public:
	 void f1()
	{
		cout << "Derive1" << endl;
	}
};
class CDerive2 : public CBse
{
public:
	 void f1()
	{
		cout << "Derive2" << endl;
	}
};
void test(CBase &cbase)
{
    cbase.f1();
}
int main()
{
	CDerive1 test1;
    CDerive1 test2;
    test(test1);
    test(test2);
	
}

 

這樣定義的話就會涉及到類型別轉換問題,通過父類型別的指標或者引用指向子類物件,即這樣,指標或者引用到底指向什麼呢?