C 特性之多型性

2021-06-19 02:05:06 字數 2457 閱讀 7336

c++多型性概括為「乙個介面,多種方法」,程式在執行時才決定呼叫的函式,它是物件導向程式設計領域的核心概念。

c++多型性是通過虛函式來實現的,虛函式允許子類重新定義成員函式,而子類重新定義父類的做法成為覆蓋或者重寫,(重寫可以有兩種,直接重寫成員函式和重寫虛函式,只有重寫了虛函式的才能算作體現了c++多型性)而過載則是允許有多個同名的函式,而這些函式的引數列表不同,允許引數個數不同,引數型別不同,或者兩者都不同。編譯器會根據這些函式的不同列表,將同名的函式的名稱做修飾,從而生成一些不同名稱的預處理函式,來實現同名函式呼叫時的過載問題,但並沒有體現多型性。

多型與非多型的實質區別就是函式位址是早繫結還是晚繫結,如果函式的呼叫,在編譯器編譯期間接可以確定函式的呼叫位址,並生產**,是靜態的,就是說位址是早繫結的。而如果函式呼叫的位址不能在編譯器期間確定,需要在執行時才確定,這就屬於晚繫結。

那麼多型的作用是什麼?封裝可以使得**模組化,繼承可以擴充套件已存在的**,他們的目的都是為了**重用。而多型的目的則是為了介面重用,也就是說,不論傳遞過來的究竟是那個類的物件,函式都能夠通過同乙個介面呼叫到適應各自物件的實現方法。

最常見的用法就是宣告基類的指標,利用該指標指向任意乙個子類物件,呼叫相應的虛函式,可以根據指向的子類的不同而實現不同的方法。如果沒有使用虛函式的話,即沒有利用c++多型性,則利用基類指標呼叫相應的函式的時候,將總被限制在基類本身,而無法呼叫到子類中被重寫過的函式。因為沒有多型性,函式呼叫的位址將是一定的,而固定的位址將始終呼叫到同乙個函式,這就無法實現乙個介面,多種方法的目的。

#include

using namespace std;

class a

public:

void foo()

virtual void fun()

class b : public a

public:

void foo()

void fun()

int main(void)

a a;

b b;

a *p = &a;

p->foo();

p->fun();

p = &b;

p->foo();

p->fun();

return 0;

輸出結果:

p是基類指標指向子類物件,體現了多型的用法,p->foo()由於指標是個基類指標,指向是乙個固定偏移量的函式,因此此時指向的就只能是基類的foo()函式,因此輸出的結果還是1,而p->fun()指標是基類指標,指向的fun是乙個虛函式,由於每個虛函式都有乙個虛函式列表,此時p呼叫fun()並不是直接呼叫函式,而通過虛函式列表找到相應的函式位址,因此根據指向的物件不同,函式位址也不同,這裡將找到對應的子類fun()函式位址。

b *ptr = (b *)&a; ptr->foo(); ptr->fun();

這是用子類的指標指向乙個強制轉換為子類位址的基類物件,結果輸出是3,2

由於ptr是子類指標,雖然被賦予基類物件位址,但是ptr->foo()在呼叫的時候,由於位址偏移量固定,偏移量是子類物件的偏移量,於是即使在指向了乙個基類物件的情況下,還是呼叫了子類的函式。而ptr->fun()的呼叫,因為c++多型性的原因,由於指向的是乙個基類物件,通過虛函式列表的引用,找到了基類中fun()函式的位址,因此呼叫了基類的函式。

#include

using namespace std;

class base

public:

virtual void f(float x)

void g(float x)

void h(float x)

class derived : public base

public:

virtual void f(float x)

void g(int x)

void h(float x)

int main(void)

derived d;

base *pb = &d;

derived* pd = &d;

pb->f(3.14);

pd->f(3.14);

pb->g(3.14);

pd->g(3.14);

pb->h(3.14);

pd->h(3.14);

return 0;

本來區別過載與覆蓋並不困難。但是c++的隱藏規則使問題複雜了

這裡隱藏是指派生類的函式遮蔽了與其同名的基類函式,規則如下:

1)、如果派生類的函式與基類的函式同名,但是引數不同,此時,不論有無virtual關鍵字,基類的函式將被隱藏f

2)、如果派生類的函式與基類的函式同名,並且引數也相同,但是基類函式沒有virtual關鍵字,此時基類的函式被隱藏

因此,函式derived::f(float)覆蓋了base::f(float)

函式derived::g(int)隱藏了base::g(float),而不是過載

函式derived::h(float)隱藏了base::h(float),而不是覆蓋

Java 特性之多型性

重寫 父類引用指向子類物件 add int,int add int,int,int add int,int add int,float add int,float add float,int int add int,int float add int,int public class animal ...

c 之 多型性

先看乙個例子 然後我們引進多型,看看 公升級的威力 1 include2 using namespace std 34 class liberation 10virtual intcombat 1114 private 15 intcapability 16 17class liberation a...

C 學習之多型性

類的幾個重要特性之一多型性,有著廣泛的用途。類的多型性包括 編譯時多型和執行時多型。編譯時多型表現為乙個同名的方法會根據引數型別 個數和位置的不同有不同執行效果。通過方法過載來實現。顧名思義,它由編譯器根據呼叫引數的不同,選擇相應的函式。執行時多型通過虛方法實現。表現為 相同的引數,仍會執行不同的函...